C Socket编程:客户端输入与服务端交互代码问题排查
C语言Socket客户端与服务端代码修正方案
核心问题梳理
客户端问题
- scanf参数不匹配:原代码
scanf("%c",&letter);中,letter是字符数组,&letter的类型是char(*)[1024],与scanf期望的char*类型不符,导致编译警告。应改为scanf(" %c", letter);(数组名本身指向首地址,前面加空格跳过输入缓冲区的空白字符)。 - 逻辑顺序错误:原代码先执行
read循环等待服务端数据,再发送指令,这会导致程序卡在read步骤(服务端需先收到指令才会返回数据),必须调整为先发送指令,再接收响应。 - 发送/输出错误:发送时不应传递整个数组长度
sizeof(letter),只需发送单个字符(长度为1);输出服务端响应时,printf("%c", recvBuff);错误,应使用%s输出字符串。
服务端问题
- 字符比较错误:原代码
from_client == 't'将数组指针与字符直接比较,逻辑完全错误,应取数组首元素from_client[0] == 't'进行判断。 - 字符串赋值错误:
sendBuff == "Marcus Baker"是比较操作而非赋值,需用strcpy(sendBuff, "Marcus Baker");复制字符串。 - 发送长度错误:发送时不应传递整个数组长度
sizeof(sendBuff),应发送实际字符串长度strlen(sendBuff),避免发送多余空字符。 - 退出逻辑不完善:收到
'q'时直接return 0会导致服务端异常退出,需先发送响应、关闭当前连接,再退出循环。 - 未处理recv返回值:未判断
recv的返回值,当客户端断开时会导致无效操作,需处理recv_len <= 0的情况。
修正后的服务端代码
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/types.h> #include <time.h> int main(int argc, char *argv[]) { int listenfd, connfd; struct sockaddr_in serv_addr; char sendBuff[1025]; char from_client[1025]; time_t ticks; ssize_t recv_len; listenfd = socket(AF_INET, SOCK_STREAM, 0); memset(&serv_addr, 0, sizeof(serv_addr)); memset(sendBuff, 0, sizeof(sendBuff)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(5000); bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); listen(listenfd, 10); while(1) { connfd = accept(listenfd, (struct sockaddr*)NULL, NULL); if (connfd < 0) { perror("accept error"); continue; } recv_len = recv(connfd, from_client, sizeof(from_client)-1, 0); if (recv_len <= 0) { close(connfd); continue; } from_client[recv_len] = '\0'; // 添加字符串结束符 printf("Received: %c\n", from_client[0]); if(from_client[0] == 't') { ticks = time(NULL); snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks)); write(connfd, sendBuff, strlen(sendBuff)); } else if(from_client[0] == 'n') { strcpy(sendBuff, "Marcus Baker"); send(connfd, sendBuff, strlen(sendBuff), 0); } else if(from_client[0] == 'i') { strcpy(sendBuff, "201604543"); send(connfd, sendBuff, strlen(sendBuff), 0); } else if(from_client[0] == 'q') { strcpy(sendBuff, "Quit"); send(connfd, sendBuff, strlen(sendBuff), 0); close(connfd); break; // 退出循环,关闭服务端 } else { strcpy(sendBuff, "Invalid command"); send(connfd, sendBuff, strlen(sendBuff), 0); } close(connfd); sleep(1); } close(listenfd); return 0; }
修正后的客户端代码
#include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { int sockfd, n = 0; char letter[2]; // 仅存储单个字符+字符串结束符 char recvBuff[1024]; struct sockaddr_in serv_addr; if(argc != 2) { printf("\n Usage: %s <ip of server> \n", argv[0]); return 1; } printf("Enter a Character (t, n, i, q): "); // 空格跳过空白字符,避免读取输入缓冲区残留的换行符 scanf(" %c", letter); memset(recvBuff, 0, sizeof(recvBuff)); if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { printf("\n Error : Could not create socket \n"); return 1; } memset(&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(5000); if(inet_pton(AF_INET, argv[1], &serv_addr.sin_addr) <= 0) { printf("\n inet_pton error occured\n"); return 1; } if( connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) { printf("\n Error : Connect Failed \n"); return 1; } // 先发送指令给服务端 int toServer = send(sockfd, letter, 1, 0); if (toServer < 0) { perror("send error"); close(sockfd); return 1; } printf("Letter Sent\n"); // 接收服务端响应 n = read(sockfd, recvBuff, sizeof(recvBuff)-1); if (n > 0) { recvBuff[n] = '\0'; printf("Server Response: %s\n", recvBuff); } else if (n < 0) { printf("\n Read error \n"); } close(sockfd); return 0; }
内容的提问来源于stack exchange,提问作者Marcus Baker
相关产品推荐
相关产品推荐

