为何带错误检测的C语言简易服务器无法正常运行?
C简易服务器添加错误检测后无法正常运行的问题
我正在用C语言写一个简易服务器,以下代码能正常运行,访问127.0.0.1:9001时页面会显示buffer里的内容:
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> int main() { char buffer[255] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"; int serverSocket, clientSocket; serverSocket = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in serverAdress; serverAdress.sin_family = AF_INET; serverAdress.sin_port = htons(9001); serverAdress.sin_addr.s_addr = INADDR_ANY; bind(serverSocket, (struct sockaddr*)&serverAdress, sizeof(serverAdress)); listen(serverSocket, 2); clientSocket = accept(serverSocket, NULL, NULL); send(clientSocket, buffer, sizeof(buffer), 0); return 0; }
但添加错误检测后的代码却无法正常运行:移除部分错误检测(比如accept的检测)能恢复正常;移除bind的检测后有时能运行,但多数情况下页面加载一秒就断开,现象很怪异,麻烦帮忙解惑。
带错误检测的代码:
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> int main() { char buffer[255] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"; int serverSocket, clientSocket; serverSocket = socket(AF_INET, SOCK_STREAM, 0); if(serverSocket<0) { printf("Socket creation failed\n"); } struct sockaddr_in serverAdress; serverAdress.sin_family = AF_INET; serverAdress.sin_port = htons(9001); serverAdress.sin_addr.s_addr = INADDR_ANY; bind(serverSocket, (struct sockaddr*)&serverAdress, sizeof(serverAdress)); //if(bind(serverSocket, (struct sockaddr*)&serverAdress, sizeof(serverAdress))!=0) //{ // printf("Socket bind failure\n"); //} if(listen(serverSocket, 2)!=0) { printf("Listen failed\n"); } clientSocket = accept(serverSocket, NULL, NULL); //if(clientSocket = accept(serverSocket, NULL, NULL)==-1) //{ // printf("Accept connection failed\n"); //} int result=0; if(result=send(clientSocket, buffer, sizeof(buffer), 0)==-1) { printf("Transmission send failed\n"); } //printf("%d\n", result); return 0; }
问题根源分析
你的代码里有两个核心错误,都是运算符优先级导致的,还有一个隐性的错误处理逻辑问题:
被注释掉的accept检测代码:
if(clientSocket = accept(serverSocket, NULL, NULL)==-1)==的优先级比=高,实际执行顺序是clientSocket = (accept(...) == -1),也就是把比较结果(0或1)赋值给了clientSocket,而非accept返回的有效套接字描述符,后续send自然无法正常通信。send的错误检测代码:
if(result=send(clientSocket, buffer, sizeof(buffer), 0)==-1)同样的优先级问题,实际是
result = (send(...) == -1),即便send正常执行,你也只是把比较结果赋值给了result,而非实际发送的字节数。错误检测后未终止程序:比如socket创建失败后,serverSocket是负数,但你没有退出程序,后续继续用这个无效套接字执行bind、listen等操作,会引发一系列连锁错误,这也是怪异现象的来源。
修复后的代码
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> // 用于exit()函数 int main() { char buffer[255] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"; int serverSocket, clientSocket; serverSocket = socket(AF_INET, SOCK_STREAM, 0); if(serverSocket < 0) { printf("Socket creation failed\n"); exit(EXIT_FAILURE); // 创建失败直接终止程序 } struct sockaddr_in serverAdress; serverAdress.sin_family = AF_INET; serverAdress.sin_port = htons(9001); serverAdress.sin_addr.s_addr = INADDR_ANY; if(bind(serverSocket, (struct sockaddr*)&serverAdress, sizeof(serverAdress)) != 0) { printf("Socket bind failure\n"); close(serverSocket); // 关闭已创建的套接字再退出 exit(EXIT_FAILURE); } if(listen(serverSocket, 2) != 0) { printf("Listen failed\n"); close(serverSocket); exit(EXIT_FAILURE); } clientSocket = accept(serverSocket, NULL, NULL); if(clientSocket == -1) // 先赋值,再判断是否出错 { printf("Accept connection failed\n"); close(serverSocket); exit(EXIT_FAILURE); } ssize_t result = send(clientSocket, buffer, sizeof(buffer), 0); if(result == -1) { printf("Transmission send failed\n"); } printf("Sent %zd bytes\n", result); // 打印实际发送字节数 // 关闭所有打开的套接字,释放资源 close(clientSocket); close(serverSocket); return 0; }
关键修复点
- 修正运算符优先级:先完成函数调用与赋值,再进行比较判断,避免逻辑错位。
- 错误发生后立即终止程序,并关闭已创建的套接字,防止无效操作引发的异常。
- send返回值类型为
ssize_t,替换int避免类型截断问题。 - 程序结束前关闭所有套接字,养成资源管理的良好习惯。
内容的提问来源于stack exchange,提问作者TheLizardQueen
相关产品推荐
相关产品推荐

