我正在用 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/