如何正确使用recv()读取客户端输入?现有代码存在两类异常问题
Socket recv读取客户端输入的异常问题
实现代码
string readMessage(SOCKET clientSocket) { char buf[4096]; string storeInfo; ZeroMemory(buf, 4096); // Wait for the "Enter" key to be pressed while (true) { int bytes = recv(clientSocket, buf, 4096, 0); if (bytes == SOCKET_ERROR) { cerr << "Error or invalid input, please try again!" << buf << endl; continue; // Restart the loop } for (int i = 0; i < bytes; i++) { storeInfo += buf[i]; if (buf[i] == 13) // 13 is the ASCII code for "Enter" { cout << " input:-" << storeInfo << "----" << endl; ZeroMemory(buf, 4096); storeInfoPtr = &storeInfo; return storeInfo; storeInfo = ""; } } } }
遇到的问题
- 控制台输出异常:存在乱码、文本截断(如"input"被截断)及符号错位情况
- 指针访问失效:使用指针
storeInfoPtr访问storeInfo内容时,首次可正常显示"placeholder",但后续读取输入后指针指向内容为空
控制台输出示例
DESKTOP-AFNABTM.lan connected on port 2282 ----ut:- √▼ √ √↑ √' ²☺ √♥ ²♥finley bad username! ----ut:-fishsticks bad username! ----ut:-falcon bad username! ----ut:-falcon bad username! ----ut:-p3anutbutt3r bad username!
终端输入示例
please enter a username: placeholderfinley bad username please enter a username: fishsticks bad username please enter a username: falcon bad username please enter a username: falcon bad username please enter a username: p3anutbutt3r bad username please enter a username:
问题原因及修复方案
问题1:控制台输出异常
原因
- 仅判断了ASCII 13(回车CR),但客户端输入回车后通常发送CR+LF(13+10)组合,未处理的LF会留在后续缓存中引发乱码
storeInfo包含CR字符,输出时CR会让光标回到行首,覆盖之前的" input:-"文本,导致截断错位
修复
- 过滤CR(13)和LF(10)控制字符,避免干扰输出
- 遇到换行相关字符时,确保只返回有效输入内容
问题2:指针访问失效
原因
storeInfo是函数局部变量,函数返回后会被销毁,storeInfoPtr指向的是已释放的内存,属于野指针,首次显示正常是内存未被覆盖的巧合
修复
- 优先直接使用函数返回的
string副本,避免使用指针 - 若必须用指针,需在堆上分配内存(如
new string),并注意在合适时机释放,避免内存泄漏
修改后的代码示例
#include <iostream> #include <string> #include <winsock2.h> using namespace std; string* storeInfoPtr = nullptr; string readMessage(SOCKET clientSocket) { char buf[4096]; string storeInfo; ZeroMemory(buf, 4096); while (true) { int bytes = recv(clientSocket, buf, 4096, 0); if (bytes == SOCKET_ERROR) { cerr << "输入错误,请重试!" << endl; continue; } else if (bytes == 0) { cerr << "客户端已断开连接" << endl; return ""; } for (int i = 0; i < bytes; i++) { // 跳过换行控制字符 if (buf[i] == 13 || buf[i] == 10) { if (!storeInfo.empty()) { cout << " input:-" << storeInfo << "----" << endl; // 堆分配避免野指针 if (storeInfoPtr != nullptr) { delete storeInfoPtr; } storeInfoPtr = new string(storeInfo); return storeInfo; } continue; } storeInfo += buf[i]; } } } // 程序结束前清理堆内存 void cleanup() { if (storeInfoPtr != nullptr) { delete storeInfoPtr; storeInfoPtr = nullptr; } }
内容的提问来源于stack exchange,提问作者Abdumumin khan
相关产品推荐
相关产品推荐

