You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确使用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 = "";

            }
        }
    }
}

遇到的问题

  1. 控制台输出异常:存在乱码、文本截断(如"input"被截断)及符号错位情况
  2. 指针访问失效:使用指针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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:03:13