我正在创建一个程序,可以通过C ++获取包并将其打印到控制台。 我将char数组设置为1024,如:
char* buffer = new char[1024];
当我收到一条消息不完全是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();
服务器由C ++控制台应用程序编写
char* recvData = new char[1024];
recv(socket, recvData, strlen(recvData), 0);
cout << recvData << endl;
答案 0 :(得分:7)
代码有三个问题:
recvData
时,strlen()
会被统一。 strlen()
确定缓冲区在找到空终止字符时的长度,该字符可能在缓冲区内或外部。缓冲区的大小,少于终止空字符的大小,应作为要读取的最大字节数传递。recv()
的结果。即使recvData
失败,代码也将使用recv()
,这是一个错误。recv()
不会终止缓冲区。保存recv()
的结果,如果不是-1
,则将其用作recvData
的索引,以插入空终止字符。
或者,因为这是c ++使用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;
}
请记住,通过套接字发送的数据只是一个字节流,它不会分成不同的消息。这意味着:
out.write("I am your client :D");
单次调用recv()
无法读取。同样:
out.write("I am your client :D");
out.write("OK");
只需一次调用recv()
即可读取 。如果需要基于消息的处理,程序员有责任实施协议。
答案 1 :(得分:5)
strlen
计算遇到null('\0'
)字符之前的字节数。无法保证单个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;
}
答案 2 :(得分:1)
recvData
不是 null终止,因此strlen()
的结果在这种情况下是未定义的。你必须做类似以下的事情:
int len = 1024;
char *recvData = new char[len + 1];
int lenRead = recv(socket, recvData, len, 0);
if (lenRead < len)
recvData[lenRead] = '\0';
else
recvData[len] = '\0';
cout << recvData << endl;
答案 3 :(得分:0)
这不是很明显吗? :)
首先发送字符串的长度或者“正确”终止字符串(在字符串结束后发送\0
;我猜这是Java在这里没有做的事情。)
但总的来说,你应该包括“数据包长度”,因为你可能想要在写入缓冲区之前确保有足够的可用空间(在未初始化的数组上使用strlen()
通常是一个坏主意。)< / p>