【发布时间】:2020-06-19 19:24:09
【问题描述】:
我有一个服务器连接到客户端并执行以下通信:
void communicate(promise<long> && divisions, promise<long> && result, int sockt, long number, long prime) {
send(sockt, number);
send(sockt, prime);
long div = receive(sockt);
long res = receive(sockt);
divisions.set_value(div);
result.set_value(res);
}
void send(int sockt, long number) {
string numberString;
stringstream strstream;
strstream << number;
strstream >> numberString;
cout << "Sending: " << number << endl;
write(sockt, numberString.c_str(), sizeof numberString);
}
long receive(int sockt) {
// receive string
const unsigned int MAX_BUF_LENGTH = 1024;
std::vector<char> buffer(MAX_BUF_LENGTH);
std::string rcv;
recv(sockt, &buffer[0], buffer.size(), 0);
rcv.append(buffer.cbegin(), buffer.cend());
//convert string to long
string::size_type sz = 0;
long val = stoll(rcv, &sz, 0);
cout << "Received: " << val << endl;
return val;
}
客户端执行相同的通信但相反:
void communicate(){
string number = receive(sockt);
string prime = receive(sockt);
// do stuff to the data
send(sockt, divisions);
send(sockt, val);
}
问题是服务器有时(在循环此通信 100 多次后)没有收到来自客户端的第二条发送消息并挂起。客户端从服务器接收消息永远不会遇到问题,它总是服务器挂起。服务器打印:
Sending: 344486269
Sending: 7
Received: 0
然后不会终止,所以我知道它在等待永远不会出现的第二个值。客户端打印:
Received: 344486269
Received: 7
Sending: 0
Sending: 344486269
所以我知道客户端成功执行了它的send() 命令。
什么可能导致服务器无法正确接收第二条消息?
【问题讨论】:
-
我怀疑如果您使用的是 tcp,则在接收时您可能已经收到超过上一次发送的结束(因为在 tcp 中您将接收流中的数据包,因此您没有消息边界) .解决此问题的一种方法是使用恒定的消息大小(例如:您可以使用一些固定大小的 int 而不是使用 asciiz),或者您可以接收每个字节的字节并将 0x00 视为 tbe 消息的结尾。
-
您几乎可以肯定在一次接收中接收到两个发送。这段代码还有其他几个问题,比如使用
sizeof' instead ofstrlen()`。太宽泛了。 -
假设我将要发送的字符串标准化为 10 个字符长,您将如何修改我的接收方法以确保我始终收到 10 个字符长的字符串?将缓冲区的大小设置为 10 字节对我不起作用。
-
提供 10 个字符的缓冲区并使用 MSG_WAITALL。