我遇到一些使用套接字的基本客户端 <-> 服务器通信的奇怪问题。
服务器通过使用 ostringstream
对象和一些简单的换行符和空格格式将数据转储到一个长字符串中来打包包含播放器信息的结构数组,然后通过套接字将该字符串发送到显示给玩家的客户端。
当被打包的一个或多个结构中的“名称”字段超过 4 个字符时,就会出现问题;如果是这种情况,每个包含 5 个以上字符的“名称”字段中第 4 个之后的每个字符都会在发送到客户端的字符串 AFTER* 末尾的一行中重复。
*打包后的字符串始终在服务器端正确显示。
下面是相关代码和两张服务端和客户端的截图,一张有报错,一张没有。
服务器代码:
struct leader_board_pos
{
string name;
int score;
};
leader_board_pos leader_board[num_players];
....
// Package and send the current leaderboard to the client
int i = 0;
string leader_board_package;
string dubspace = " ";
ostringstream oss;
cout << "Package leader board > "; cin.ignore();
leader_board_package = "Leader Board: \n";
while(i < num_leaders)
{
oss << leader_board[i].name << dubspace << leader_board[i].score << endl;
leader_board_package += oss.str();
oss.str(string());
i++;
}
cout << leader_board_package; cin.ignore();
bytes_sent = send(clientSock, leader_board_package.c_str(), leader_board_package.length(), 0);
if (bytes_sent != leader_board_package.length())
{
cout << "Server Message: Communication error..." << endl;
return;
}
客户端代码:
const int MAX_BUFF_LENGTH = 4096;
...
//Get and display Leaderboard
int bytes_recv = 0;
vector<char> leader_board_buffer(MAX_BUFF_LENGTH);
string leader_board_package;
do {
bytes_recv = recv(sock, leader_board_buffer.data(), MAX_BUFF_LENGTH, 0);
if (bytes_recv == -1)
{
cout << "Communication error...";
return 0;
}
else
{
leader_board_package.append(leader_board_buffer.begin(), leader_board_buffer.end());
}
} while (bytes_recv == MAX_BUFF_LENGTH);
cout << endl << endl << leader_board_package; cin.ignore();
屏幕截图,突出显示的相关部分:
除非我遗漏了其他东西,否则我 99% 确定错误出在客户端的 do-while 接收循环中,因为字符串在服务器端打印时会正确显示。我无法想象是什么导致了这样一个特定的错误,因为它只是发送了一个长字符串。
最佳答案
leader_board_package.append(leader_board_buffer.begin(), leader_board_buffer.end());
这是错误的。缓冲区仅包含 bytes_recv
的接收数据。
while (bytes_recv == MAX_BUFF_LENGTH);
如果您从片段中组装消息,则需要在某处将它们的长度相加。
此外,
if (bytes_sent != leader_board_package.length())
这也是错误的。不要依赖 send
能够一次发送整个数组。正确的发送方式是以与循环接收相同的方式循环发送。
还不清楚您的消息的大小应该是多少。如果它是可变的,则需要将其与消息一起传输。如果它是 MAX_BUFF_LENGTH,您需要发送()这个确切的字节数。您不能依赖通过 TCP 一次性发送或接收的消息。
关于c++ - 通过套接字 C++ 发送长字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37606349/