关于c++中的套接字recv和char[]
About socket recv and char[] in C++
我正在创建一个程序,可以通过c++获取软件包并将其打印到控制台。我将字符数组设置为1024,如:
char* buffer = new char[1024];
当我得到一个不完全是1024字符的消息时,由于数组中的空格,在我的消息末尾有许多未知字符。我能做什么?
更多信息(我不知道是否有用)
socket是由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;
这段代码有三个问题:
-
recvData
传递给strlen()
时被初始化。strlen()
确定缓冲区的长度,当它发现一个空终止字符,这可能是在缓冲区内或外部。缓冲区的大小,小于终止null字符的大小,应该作为要读取的最大字节数传递。 不查询 -
recv()
的结果。代码将使用recvData
,即使recv()
失败,这是一个错误。 -
recv()
不null终止缓冲区
保存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()
的单个调用读取。如果需要基于消息的处理,则程序员有责任实现协议。
strlen
计算在遇到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] = ' ';
cout << recvData << endl;
}
recvData
不是null终止,所以在这种情况下strlen()
的结果是未定义的。您必须执行如下操作:
int len = 1024;
char *recvData = new char[len + 1];
int lenRead = recv(socket, recvData, len, 0);
if (lenRead < len)
recvData[lenRead] = ' ';
else
recvData[len] = ' ';
cout << recvData << endl;
这不是很明显吗?:)
首先发送字符串的长度或"正确"终止字符串(通过在字符串结束后发送