c++ - 通过套接字进行数据传输[TCP]如何在c/c++中打包多个整数并使用send()recv()传输数据?

标签 c++ c linux sockets tcp

我正在用 c/c++ 在 Linux 上制作一个基于客户端/服务器的小型游戏,我需要将玩家发送到服务器。

这是我的问题。

我想向服务器发送两个整数,有时它工作得很好,但有时服务器在第一个recv()中接收到两个整数并且卡住了。

我知道最好的方法是打包消息。 问题是我不知道语法应该是什么样子。

理论上 --> 玩家输入就像一个 int 列 = 4 和第二个 int 行 = 1,我将消息打包为 4|1 或类似的东西。然后我从客户端发送到服务器并在服务器上对其进行编码。 一个例子会很好,或者可能提供一些建议如何处理这样的事情。 我对套接字编程还很陌生。

这是我的函数的样子:

客户:

#define BUFFER 512

void send_turn_to_server(int sock, int row, int column)
{
   // sends  row to server from player turn

   char char_row[BUFFER];
   sprintf(char_row, "%d", row);
   char *message_from_client = char_row;
   int len, bytes_sent_row;
   len = strlen(message_from_client);

   if (sendall(sock, message_from_client, &len) == -1)
   {
      perror("sendall");
      printf("We only sent %d bytes because of the error!\n", len);
   }


   char char_column[BUFFER];
   int bytes_sent_column;
   //sends column from player turn
   //sprintf converts the int to char
   sprintf(char_column, "%d", column);
   char *column_from_client = char_column;
   len = strlen(column_from_client);

   if (sendall(sock, column_from_client, &len) == -1)
   {
      perror("sendall");
      printf("We only sent %d bytes because of the error!\n", len);
   }
   cout << "send_turn_to_server_complete" << endl;
}

这里我使用了 Beej 网络编程指南中的一个函数,因此我可以确定整个缓冲区都已发送。

客户:

int sendall(int s, char *buf, int *len)
{
   int total = 0;        // how many bytes we've sent
   int bytesleft = *len; // how many we have left to send
   int n;

   while (total < *len)
   {
      n = send(s, buf + total, bytesleft, 0);
      if (n == -1)
      {
         break;
      }
      total += n;
      bytesleft -= n;
   }

   *len = total; // return number actually sent here

   return n == -1 ? -1 : 0; // return -1 on failure, 0 on success
}

服务器:

int receive_player_turn(int sock, int &int_row, int &int_column)
{
   int byte_count;
   char buf[BUFFER];
   byte_count = recv(sock, buf, sizeof buf, 0);
   cout << "The row from player: " << buf << endl;
   //The C library function int atoi(const char *str) converts the string argument str to an integer (type int).
   int_row = atoi(buf);
   //cleans the buffer
   bzero(buf, sizeof(buf));

   byte_count = recv(sock, buf, sizeof buf, 0);
   cout << buf << endl;
   cout << "The column from player: " << buf << endl;

   //converts the char string to an int
   int_column = atoi(buf);

   cout << endl

        << "receive player turn worked" << endl
        << "players turn was in the row " << int_row << " and in the column " << int_column + 1 << endl;

   return int_row, int_column;
}

服务器输出正确:

Player connected: SchleichsSalaticus
The row from player: 7
4
The column from player: 4

receive player turn worked
players turn was in the row 7 and in the column 5  
7 4

服务器输出错误:

Player connected: SchleichsSalaticus
The row from player: 74

最佳答案

问题在于 TCP 是一个连续的,没有“消息”开始或结束的概念,因为它不是基于消息的。 p>

大多数时候,人们使用非常简单的“成帧协议(protocol)”,您总是在每次传输时发送一个 4 字节 header ,告诉接收者要读取多少字节,然后您发送那么多字节作为您的消息。

使用htonl()以网络字节顺序发送4字节 header ,然后您将可以互操作。有一个非常相似的例子here .

关于c++ - 通过套接字进行数据传输[TCP]如何在c/c++中打包多个整数并使用send()recv()传输数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62874574/

相关文章:

c++ - 与 CMake 2.8 一起安装 CMake 3.3 的具体细节是什么?

从另一个目录中的源文件调用方法

linux - Linux中多核处理器从实模式到保护模式的转变

linux - CentOS登录后如何启动应用程序?

c++ - 哪个 WinAPI 库最适合将文件上传到服务器

c - C中的连续替换函数

C++ - 不正确的 ASCII 值 ("ë")

c# - 在 Linux 上使用 Mono 进行 native P/调用 : DllNotFound

c++ - 将一个数组分配给另一个数组 C++

c++ - 使用 Boost/Asio 时出现 SSL 间歇性问题