通过套接字进行数据传输[TCP]如何在c/c ++中打包多个整数并使用send()recv()传输数据? [英] Data transfer over sockets[TCP] how to pack multiple integer in c/c++ and transfer the data with send() recv()?
问题描述
我正在用c/c ++在linux上制作一个基于客户端/服务器的小型游戏,我需要将玩家回合发送到服务器.
I'm making a small client/server based game, on linux in c/c++ and I need to send the player turn to the server.
这是我的问题.
我想向服务器发送两个整数,有时它可以正常工作,但是有时服务器在第一个recv()中接收到两个整数,并且卡住了它.
I want to send two integers to the server and sometimes it works perfectly, but sometimes the server receives both integer in the first recv() and its stuck.
我知道最好的方法是打包消息.问题是我不知道语法的样子.
I know that the best way is to package the messages. The problem is I don't know how the syntax should look like.
从理论上讲->玩家输入就像一个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网络编程指南》中的一个功能,因此可以确定整个缓冲区都已发送.
Here I use a function from Beej's Guide to Network Programming, so I can be sure the whole buffer is sent.
客户:
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是连续的流,没有消息"的开始或结束的概念,因为它不是基于消息的.
The issue is that TCP is a continuous stream, with no concept of the start or end of a "message" because it is not message-based.
大多数时候,人们使用非常简单的成帧协议" ,通过这种方式,您每次传输时都会发送一个4字节的标头,告诉接收者要读取多少字节,然后发送那么多字节作为您的消息.
Most times, people use a very simple "framing protocol" whereby you always send a 4-byte header on every transfer which tells the recipient how many bytes to read, then you send that many bytes as your message.
使用 htonl()
以网络字节顺序发送4字节的标头,那么您将可以互操作.此处.
Use htonl()
to send the 4-byte header in network byte order then you will be interoperable. There is a very similar example here.
这篇关于通过套接字进行数据传输[TCP]如何在c/c ++中打包多个整数并使用send()recv()传输数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!