我正试图使用TCP/IP套接字在C++中制作一个客户端-服务器应用程序,但当我试图从服务器接收数据时,客户端会收到一个随机的大数字,即使服务器没有发送它。
在服务器端,我首先接收客户端的用户,然后发送服务器的名称和用户角色:
std::string user = Communication_Protocol::recv_message(client_sock, logger);
client.set_user(user);
int user_role = database_manager.get_user_role(user);
Communication_Protocol::send_message(client_sock, this->name, logger);
Communication_Protocol::send_message(client_sock, std::to_string(user_role), logger);
在客户端,我首先发送用户,然后接收服务器名称和用户角色:
Communication_Protocol::send_message(client_sock, username, logger);
server_name = Communication_Protocol::recv_message(client_sock, logger);
role = std::stoi(Communication_Protocol::recv_message(client_sock, logger));
logger->add("ROLE=" + std::to_string(role));
通信协议中使用的功能有:
void send_message(SOCKET socket, std::string message, Logger *logger){
std::string encapsulated_string = message;
size_t total_bytes_sent = 0;
size_t bytes_sent = 0;
size_t size = encapsulated_string.size();
send(socket, &size, sizeof(size), 0);
while (total_bytes_sent < encapsulated_string.size()){
std::string message_left = encapsulated_string.substr(bytes_sent);
bytes_sent = send(socket, message_left.c_str(), sizeof(message_left.c_str()), 0);
total_bytes_sent += bytes_sent;
logger->add_network("SEND", encapsulated_string.substr(total_bytes_sent - bytes_sent, total_bytes_sent), "<RECIVER>");
if(bytes_sent < 0){
logger->add_error("MESSAGE NOT SENT");
return;
}
}
}
std::string get_message(SOCKET socket, size_t size){
std::string message = "";
char *recv_buffer = new char[BUFFER_SIZE];
size_t bytes_recived = 0;
while (bytes_recived < size){
memset(recv_buffer, ' ', BUFFER_SIZE);
size_t len = recv(socket, recv_buffer, size - bytes_recived, 0);
if(len < 0){
throw Socket_Error_Exception();
}
if(len == 0){
throw Client_Down_Exception();
}
std::string recv_msg = std::string(recv_buffer);
message += recv_msg;
bytes_recived += len;
}
delete recv_buffer;
return message;
}
std::string recv_message(SOCKET socket, Logger *logger){
long message_size;
std::string message = "";
size_t recv_len = recv(socket, &message_size, sizeof(message_size), 0);
if(message_size > 0){
logger->add_network("RECV", "SIZE = " + std::to_string(message_size), "<SENDER>");
message = get_message(socket, message_size);
logger->add_network("RECV", "BODY = " + message, "<SENDER>");
}
return message;
}
服务器日志:
2020-8-16 16:51:45 NET RECV SIZE = 4 FROM <SENDER>
2020-8-16 16:51:45 NET RECV BODY = USER FROM <SENDER>
2020-8-16 16:51:45 NET SEND xxx TO <RECIVER>
2020-8-16 16:51:45 NET SEND -1 TO <RECIVER>
客户端日志:
2020-8-16 16:51:45 NET SEND USER TO <RECIVER>
2020-8-16 16:51:45 NET RECV SIZE = 3 FROM <SENDER>
2020-8-16 16:51:45 NET RECV BODY = xxx FROM <SENDER>
2020-8-16 16:51:45 NET RECV SIZE = 2199031643136 FROM <SENDER>
我尝试过更改消息的顺序,但只有来自服务器的第一条消息能正常接收,第二条消息的大小很大
我以为它是字符串中缺少的"\0"或溢出,但我看不到这样的错误的来源
我还认为问题来自于从数据库接收用户角色,但我曾尝试在接收sleep_for并发送硬编码整数之前放入它,但我遇到了同样的问题。
在send_message
中,消息长度使用sizeof(message_left.c_str())
。这是一个指针的大小。您可能想要message_left.size()
:
bytes_sent = send(socket, message_left.c_str(), message_left.size(), 0);
在recv_message
中,您使用的是message_size
,其中您可能希望使用返回的recv_len
,而且recv_len应该是ssize_t
,因为它可以是-1:
ssize_t recv_len = recv(socket, &message_size, sizeof(message_size), 0);
if (recv_len > 0){
在get_message
中,len也应该是ssize_t
:
ssize_t len = recv(socket, recv_buffer, size - bytes_recived, 0);