关于C++中的socket recv和char []

Jef*_*Lee 1 c++ sockets

我正在创建一个程序,可以获取包并通过C++将其打印到控制台.我将char数组设置为1024,如:

char* buffer = new char[1024];
Run Code Online (Sandbox Code Playgroud)

当我收到一条消息不完全是1024个字符时,由于数组中的空白空间,我的消息末尾有许多未知字符.我能做什么?

更多信息(我不知道它是否有用)

套接字由Java程序发送

Socket socket = new Socket("127.0.0.1", 27555);

BufferedWriter out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
out.write("I am your client :D");
out.flush(); 
Run Code Online (Sandbox Code Playgroud)

服务器由C++控制台应用程序编写

char* recvData = new char[1024];
recv(socket, recvData, strlen(recvData), 0);
cout << recvData << endl;
Run Code Online (Sandbox Code Playgroud)

hmj*_*mjd 7

代码有三个问题:

  • recvData传递给时是单元化的strlen().strlen()当找到空终止字符(可能在缓冲区内或外部)时,确定缓冲区的长度.缓冲区的大小(小于终止空字符的大小)应作为要读取的最大字节数传递.
  • 结果recv()是没有被查询.代码将使用recvData即使recv()失败,这是一个错误.
  • recv() 不为null终止缓冲区.

保存结果,recv()如果不-1将其用作索引recvData,则插入空终止字符.

或者,因为这是c ++使用a std::vector<char>并为您管理动态内存分配(如果确实需要动态内存分配):

std::vector<char> recvData(1025); // Default initializes all elements to 0.
int result = recv(socket, recvData.data(), recvData.size() - 1);
if (result != -1)
{
    std::cout << recvData.data() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

请记住,通过套接字发送的数据只是一个字节流,它不会分成不同的消息.这意味着:

out.write("I am your client :D");
Run Code Online (Sandbox Code Playgroud)

可能无法通过一次调用来读取recv().相等:

out.write("I am your client :D");
out.write("OK");
Run Code Online (Sandbox Code Playgroud)

可能只需一次调用即可阅读recv().如果需要基于消息的处理,程序员有责任实施协议.


sim*_*onc 5

strlen计算'\0'遇到null()字符之前的字节数.无法保证单个recv调用返回的数据将被终止,因此您需要检查返回的字节数,然后添加自己的终结符.

char* recvData = new char[1024];
int bytes = recv(socket, recvData, 1023, 0);
if (bytes == -1) {
    cout << "error on recv" << endl;
}
else {
    recvData[bytes] = '\0';    
    cout << recvData << endl;
}
Run Code Online (Sandbox Code Playgroud)