简介 Socket
在Unix/Linux中,为了统一各种硬件的操作,简化接口,不同的硬件设备都被看作为一个文件,对于这些文件的操作就相当于对磁盘上普通文件的操作。
Unix/Linux中的一切都是文件
为了区分已打开的文件,Unix/Linux会给每个文件分配一个整数ID(文件描述符),所以网络链接也是一个文件,同样拥有文件描述符。
通过socket()创建一个网络连接,其返回值就是一个文件描述符。
//1.sockf就是socket返回的文件描述符
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0)
{
perror("socket");
exit(-1);
}
当sock()成功执行之后,使用bind()将套接字与ip::port绑定起来,客户端使用connect()建立链接
//服务器端
struct sockaddr_in sock_addr;
bzero(&sock_addr, sizeof(sock_addr)); // 清空
sock_addr.sin_family = AF_INET; // IPv4
sock_addr.sin_port = htons(port); // 端口
sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); // ip
//2.绑定
int err_status = bind(sockfd, (struct sockaddr*)&sock_addr, sizeof(sock_addr));
if(err_status != 0)
{
perror("binding");
close(sockfd);
exit(-1);
}
//客户端
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
if (connect(client_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))==-1)
{
/* code */
printf("server connection error!\n");
return -1;
}
使用listen()让套接字进入被动监听状态,再调用accept()相应客户端请求
/3.监听,套接字变被动
err_status = listen(sockfd, 10);
if(err_status != 0)
{
perror("listen");
close(sockfd);
exit(-1);
}
while(1)
{
char client_ip[INET_ADDRSTRLEN] = {0};
struct sockaddr_in client_addr;
socklen_t cliaddr_len = sizeof(client_addr);
// 取出已完成的连接
int connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);
if(connfd < 0)
{
perror("accept");
close(sockfd);
exit(-1);
}
}
使用fork()创建子进程接受客户端消息
pid_t pid = fork();
if(pid < 0){
perror("fork");
exit(-1);
}else if(0 == pid){
//子进程 接收客户端的信息
close(sockfd); // 关闭监听套接字
char recv_buf[1024] = {0};
int recv_len = 0;
memset(client_ip, 0, sizeof(client_ip)); // 清空
inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
printf("----------------------------------------------\n");
printf("client ip=%s,port=%d\n", client_ip, ntohs(client_addr.sin_port));
// 接收数据
while( (recv_len = recv(connfd, recv_buf, sizeof(recv_buf), 0)) > 0 )
{
printf("recv_buf: %s\n", recv_buf); // 打印数据
send(connfd, recv_buf, recv_len, 0); // 给客户端回数据
}
printf("client_port %d closed!\n", ntohs(client_addr.sin_port));
close(connfd); //关闭已连接套接字
exit(0);
}
else if(pid > 0){ // 父进程
close(connfd); //关闭已连接套接字
}
Q.E.D.