套接字概述
在Linux中,一切都是文件. Linux 中的网络编程通过socket接口进行, socket是一种特殊的I/0接口, 也是一种文件描述符. 常用的进程之间通信. 下图是使用TCP协议的通信过程 :
三次握手建立连接
四次挥手断开连接
这里通过实现两个例子了解一些常用API的用法, 不废话, 直接上代码.
1.回声客户端
服务端代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<pthread.h> #include<unistd.h> #include<errno.h> #include<netdb.h> #include<sys/socket.h> #include<netinet/in.h> #include<sys/types.h> #define PORT 4321 //端口号 #define BUFFER_SIZE 1024 //缓冲区大小 #define MAX_QUE_CONN_NM 5 //最大请求队列 /* 处理客户端请求 */ void *conn_hand(void *arg){ int client_fd = *(int *)arg; int recvbytes, sendbytes; char buf_recv[BUFFER_SIZE] = {0}, buf_send[BUFFER_SIZE]; while(1){ /* 调用recv()函数, 接受客户端请求. 从缓冲区中读取. */ if((recvbytes = recv(client_fd, buf_recv, BUFFER_SIZE, 0)) == -1){ perror("recv"); break; } printf("receive from client: %s\n", buf_recv); /* 退出 */ if(strcmp(buf_recv, "quit") == 0) break; /* 向客户端发送数据 这里只是写入缓冲区, 由TCP协议发送至网络中*/ if(send(client_fd, buf_recv, recvbytes, 0) == -1){ perror("send"); break; } memset(buf_recv, 0, BUFFER_SIZE); } printf("terminating current connect...\n"); close(client_fd); pthread_exit(NULL); } int main(void){ struct sockaddr_in server_sockaddr, client_sockaddr; int sin_size; int sockfd, client_fd; /* 建立socket连接 */ if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ perror("socket"); exit(1); } printf("socket id=%d\n", sockfd); /* 设置sockaddr_in 结构体参数 */ server_sockaddr.sin_family = AF_INET; server_sockaddr.sin_port = htons(PORT); server_sockaddr.sin_addr.s_addr = INADDR_ANY; bzero(&(server_sockaddr.sin_zero),8) ; /* 允许重复本地址绑定套接字 */ int i = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)); /* 绑定函数bind() */ if(bind(sockfd, (struct sockaddr *)&server_sockaddr, sizeof(struct sockaddr)) == -1){ perror("bind"); exit(1); } printf("bind success!\n"); /* 调用listen函数监听, 创建未处理请求队列 */ if(listen(sockfd, MAX_QUE_CONN_NM) == -1){ perror("listen"); exit(1); } printf("listening port:%d ...\n", PORT); sin_size = sizeof(client_sockaddr); /* 循环接收客户端请求 */ while(1){ pthread_t tid; client_fd = accept(sockfd, (struct sockaddr *)&client_sockaddr, &sin_size); /* 创建新线程处理客户端请求*/ if(pthread_create(&tid, NULL, conn_hand, &client_fd) == -1){ perror("pthread_create"); break; } } close(sockfd); exit(0); }