Socket 客户端服务端通信
客户端和服务器执行流程
1、服务器端的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, char *argv[]) { int serv_sock, clnt_sock; char message[BUF_SIZE]; int str_len, i; struct sockaddr_in serv_adr; struct sockaddr_in clnt_adr; socklen_t clnt_adr_sz; /* 检查用户是否输入监听的端口号,端口号从argv中获取*/ if(argc!=2) { printf("Usage : %s <port>\n", argv[0]); exit(1); } /* 创建服务器的监听套接字socket*/ serv_sock=socket(PF_INET, SOCK_STREAM, 0); if(serv_sock==-1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=htonl(INADDR_ANY); serv_adr.sin_port=htons(atoi(argv[1])); /* 服务器的监听socket和指定端口和任意地址进行bind绑定 */ if(bind(serv_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1) error_handling("bind() error"); /* listen函数监听客户端请求连接,并将连接请求放进大小为5的请求等待队列中*/ if(listen(serv_sock, 5)==-1) error_handling("listen() error"); clnt_adr_sz=sizeof(clnt_adr); for(i=0; i<5; i++) { /* accept函数受理请求等待队列中的请求,拿到第一个请求就创建新链接的套接字clnt_sock用于收发消息*/ clnt_sock=accept(serv_sock, (struct sockaddr*)&clnt_adr, &clnt_adr_sz); if(clnt_sock==-1) error_handling("accept() error"); else printf("Connected client %d \n", i+1); while((str_len=read(clnt_sock, message, BUF_SIZE))!=0) write(clnt_sock, message, str_len); /* 关闭用于收发消息的TCP套接字 */ close(clnt_sock); } /* 关闭用于服务器端监听套接字 */ close(serv_sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
2、客户端的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #define BUF_SIZE 1024 void error_handling(char *message); int main(int argc, char *argv[]) { int sock; char message[BUF_SIZE]; int str_len; struct sockaddr_in serv_adr; if(argc!=3) { printf("Usage : %s <IP> <port>\n", argv[0]); exit(1); } /* 创建连接服务器的TCP套接字*/ sock=socket(PF_INET, SOCK_STREAM, 0); if(sock==-1) error_handling("socket() error"); memset(&serv_adr, 0, sizeof(serv_adr)); serv_adr.sin_family=AF_INET; serv_adr.sin_addr.s_addr=inet_addr(argv[1]); serv_adr.sin_port=htons(atoi(argv[2])); /* 根据TCP套接字向发起连接请求,*/ if(connect(sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1) error_handling("connect() error!"); else puts("Connected..........."); while(1) { fputs("Input message(Q to quit): ", stdout); fgets(message, BUF_SIZE, stdin); if(!strcmp(message,"q\n") || !strcmp(message,"Q\n")) break; /* 向socket中写入消息,并从中读出消息*/ write(sock, message, strlen(message)); str_len=read(sock, message, BUF_SIZE-1); message[str_len]=0; printf("Message from server: %s", message); } /* 循环结束,关闭套接字,断开连接 */ close(sock); return 0; } void error_handling(char *message) { fputs(message, stderr); fputc('\n', stderr); exit(1); }
3、执行结果
①首先启动服务器端监听端口 10000
② 然后启动客户端,向服务端发起连接,并进行输入输出,输入q断开连接
③ 查看服务器端:
④ 客户端重新发起连接
⑤ 查看服务器端,标记连接第二个客户端
⑥因为设置的队列长度为5,所以可以有5次客户端连接请求,第六次连接就会失败
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南