当前位置: 首页 > 知识库问答 >
问题:

TCP/IP套接字接收随机大数

上官和惬
2023-03-14

我试图使用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, '\0', 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,但也遇到了同样的问题。

共有1个答案

景靖琪
2023-03-14

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);
 类似资料:
  • 我使用Android应用程序通过TCP套接字与同一局域网上的PC java应用程序进行通信、发送和接收消息。下面是我在android中使用的Asynctask的代码,用于发送消息并从PC接收回复: } 我在onPostExcecute中的祝酒词中显示PC的回复。 Android通过BufferedWriter发送消息,而PC上的java应用程序在BufferedReader中接收消息。 PC在收到

  • 当我尝试接收大量数据时,它会被切断,我必须按enter键才能获取其余数据。起初,我可以增加一点,但它仍然不会收到所有的。正如您所看到的,我增加了conn.recv()上的缓冲区,但它仍然无法获取所有数据。它会在某一点切断它。我必须在原始输入上按enter键才能接收其余数据。我是否可以一次获取所有数据?这是密码。

  • 问题内容: 我要通过TCP / IP编写程序,我应该通过客户端或服务器发送对象,当我想发送或接收字符串但尝试读取对象时,它是正确的: 我收到一个例外: 它指的是这一行: 这是我的服务器代码: 客户端代码: 谁能解释我发生了什么,这个例外是什么,为什么我收到这个例外? 问题答案: 只是摆脱发送和接收布尔值的麻烦。这是多余的。如果在创建连接时遇到问题,则不会创建套接字:而是抛出异常。您会将所有内容与同

  • 问题内容: 我已经用套接字卡住了4h,我使用的方式是只有一个应用程序作为客户端和服务器,一旦客户端连接, 它将与新客户端一起打开theard,并等待消息。 一旦消息发送到服务器,客户端将收到响应,该部分正在正常工作。 客户专区的一部分: 服务器支持2条消息,第一条是“列表”,发送一条命令是“获取值”。 如果客户端将请求命令“列表”,它将运行以下命令:有一个“服务器/客户端”,它正在发送请求并接收一

  • 在这里搜索我的问题,我发现了更多关于这个的讨论,但似乎这个解决方案并不简单,发送一个带有套接字的结构。 我不明白如何在安全模式下发送带有套接字的结构。 我需要使用struct来发送我的信息,并正确地接收它,而不丢失任何数据。 所以,情况是这样的:客户端必须向服务器发送这个结构: 其中 Matrix4x4 是这样的: 要发送的每一个数据包,都要改变矩阵,布尔为真或假;我需要接收它,并可以访问布尔和矩

  • 我有一个很奇怪的问题快把我逼疯了。 我有一个Ruby服务器和一个Flash客户端(动作脚本3)。这是一个多人游戏。 问题是,一切都在完美地工作,然后,突然,一个随机的球员停止接收数据。当服务器因为不活动而关闭连接时,大约20-60秒后,客户端接收到所有缓冲的数据。 null 我不认为这是一个操作系统/网络问题,因为我已经从一个位于西班牙的VPS换到了位于爱尔兰的亚马逊EC2,问题仍然存在。 我觉得

  • 我正在编写一个c#tcp套接字服务器,它将从c套接字应用程序接收数据。现在,除了我的c#接收线程中的循环中断逻辑外,其他一切都正常工作。为了更好地解释,我在下面展示了一段代码片段。 下面是连续接收数据的线程函数 为了更好地了解情况,我在我的通讯协议下面写了一些东西。 客户端发起连接。发送数据集 服务器接收,处理,发送ack 客户端处于停止模式,直到它收到来自服务器的ack,但没有关闭套接字 这一次

  • 我使用服务器-客户机模型与使用套接字编程的硬件板进行通信。 我使用“NetworkStream”类的“read()”方法从板上接收数据,该方法读取指定最大大小的缓冲区,并返回缓冲区中有效数据的长度。我已经考虑了一个足够大的数字缓冲区的最大大小。 该板每100ms发送一组消息。每条消息包含一个2字节的常量报头和一个作为报头字节之后的数据的可变字节数。