C++ Socket通信中recv()返回长度正确但接收缓冲区内容异常问题
问题原因
- 核心错误出在客户端
send_Buffer函数的send调用参数错误:send函数第二个参数要求传入待发送数据的首地址,你传入的是&sendMessage,也就是char*类型指针本身的栈地址,而非指针指向的字符串"Test"的内存地址,导致实际发送的是栈上指针变量的内存值,而非目标字符串内容。所以服务端收到的4字节其实是指针变量的前4个字节,自然打印出来是乱码。 - 额外错误点:
- 服务端直接用
printf("%s")打印接收缓冲区,%s要求字符串以\0结尾,就算修复发送逻辑,如果发送的数据不带结束符也会出现打印异常。 - 服务端
send调用时传入&sendBuff也是错误的,sendBuff本身就是数组首地址,不需要取地址,多余的&会发送栈上数组指针的地址而非数组内容。 - 客户端调用
sendmsg+="\0"是冗余操作,std::string的c_str()返回的字符串本身就自带末尾\0,不需要额外添加。 - TCP是字节流协议,单次
recv不一定能拿到完整的全部数据,后续如果发送长包需要额外处理粘包问题,当前测试短包暂时不影响但需要注意。
- 服务端直接用
修复方案
1. 修复客户端send_Buffer函数
去掉send参数里sendMessage前的取地址符&,修改后代码:
void Client_Connector::send_Buffer(char* sendMessage) { int i; // 直接传指针本身即字符串首地址,不要取指针的地址 i=send(sock, sendMessage, strlen(sendMessage)+1,0); cout<<i<<endl; }
2. 修复服务端收发逻辑
while(1) { int length=sizeof(client); connSock=accept(readSock, (struct sockaddr*) &client,&length); if(!fork()) { close(readSock); // 初始化缓冲区避免脏数据 char receiveBuff[1000] = {0},sendBuff[1000] = {0}; int status; do { // 预留1字节位置放字符串结束符,避免越界 status=recv(connSock, receiveBuff, 999,0); if(status > 0) { // 手动加结束符保证字符串打印正常 receiveBuff[status] = '\0'; printf("%d status \n",status); printf("%s recv buff\n", receiveBuff); // 只复制实际收到的字节,不要复制整个缓冲区 memcpy(sendBuff,receiveBuff,status); // 去掉sendBuff前的&,只发送实际收到的字节长度 send(connSock, sendBuff, status, 0); // 清空缓冲区避免下次接收残留旧数据 memset(receiveBuff, 0, sizeof(receiveBuff)); memset(sendBuff, 0, sizeof(sendBuff)); } }while (status > 0); // 连接断开或者出错就退出循环 close(connSock); exit(0); } close(connSock); }
3. 可选优化客户端调用逻辑
删除冗余的加\0操作:
connecter.Start_Connection(); string sendmsg("Test"); // 无需手动加\0,c_str()返回的字符串自带结束符 connecter.send_Buffer((char*)sendmsg.c_str());
内容的提问来源于stack exchange,提问作者dy3zz1
相关产品推荐
相关产品推荐

