gpt4 book ai didi

c++ - 在 C++ 中通过套接字传输数据

转载 作者:可可西里 更新时间:2023-11-01 02:33:33 26 4
gpt4 key购买 nike

我目前正在从事一个使用网络的项目。我必须发送一个结构

    struct Header
{
uint32_t magic;
uint32_t checksum;
uint32_t timestamp;
uint16_t commandId;
uint16_t dataSize;
};

struct Packet
{
struct Header header;
char data[128];
};

我正在尝试使用 TCP 将结构包从一个套接字发送到另一个套接字。我试过那样发送我的结构

      send(socket, &my_struct, sizeof(my_struct), 0);

但它不起作用,所以我尝试将我的结构序列化为 char*

unsigned char               *Serialization::serialize_uint32(unsigned char *buffer, uint32_t arg)
{
buffer[3] = (arg >> 24);
buffer[2] = (arg >> 16);
buffer[1] = (arg >> 8);
buffer[0] = (arg);
return (buffer + sizeof(uint32_t));
}

unsigned char *Serialization::serialize_uint16(unsigned char *buffer, uint16_t arg)
{
buffer[1] = (arg >> 8);
buffer[0] = (arg);
return (buffer + sizeof(uint16_t));
}

unsigned char *Serialization::deserialize_uint32(unsigned char *buffer, uint32_t *arg)
{
memcpy((char*)arg, buffer, sizeof(uint32_t));
return (buffer + sizeof(uint32_t));
}

unsigned char *Serialization::deserialize_uint16(unsigned char *buffer, uint16_t *arg)
{
memcpy((char*)arg, buffer, sizeof(uint16_t));
return (buffer + sizeof(uint16_t));
}

即使客户端简单地发送一个结构头数据,当我在服务器端读取它时数据也已损坏为什么数据损坏?

客户端发送循环

    TcpSocket                     tcp;
Packet p;
std::stringstream ss;
int cpt = 0;
int ret = 0;
char *serialized;

tcp.connectSocket("127.0.0.1", 4242);
while (getchar())
{
ss.str("");
ss.clear();
ss << cpt++;
p.header.magic = 0;
p.header.checksum = 1;
p.header.timestamp = 2;
p.header.commandId = 3;
p.header.dataSize = ss.str().length();
memset(p.data, 0, 128);
memcpy(p.data, ss.str().c_str(), ss.str().length());
serialized = new char[sizeof(Header) + ss.str().length()];
bzero(serialized, sizeof(Header) + ss.str().length());
Serialization::serialize_packet(serialized, p);
hexDump("serialized", serialized+1, sizeof(Header) + ss.str().length());
ret = tcp.write(serialized+1, sizeof(Header) + ss.str().length());
}

服务器接收循环:(由 select() 调用的函数)

  buff = new char[bav];
socket->read(buff, bav);
hexdump("buff", buff, bav);

套接字->读取():

    int                     TcpSocket::read(char *buff, int len)
{
int ret;

ret = recv(this->_socket, buff, len, 0);
return (ret);
}

当我运行这些程序时:

    ./server
[Server] new connexion :: [5]
recv returns : 17
buff serialized:
0000 00 00 00 00 14 00 00 00 1c 00 00 00 1a 00 00 00 ................
0010 1b

./client
serialized data:
0000 00 00 00 00 00 00 01 00 00 00 02 00 03 00 01 30 ...............0
0010 00
send returns : 17

最佳答案

所以,这是错误的,而且肯定会出错。

buff = new char[bav];
socket->read(buff, bav);
hexdump("buff", buff, bav);
socket->read() :

int TcpSocket::read(char *buff, int len)
{
return recv(this->_socket, buff, len, 0);
}

不能忽略 recv() 的返回值。

来自 man 2 recv:

RETURN VALUES     These calls return the number of bytes received, or -1 if an error     occurred.     For TCP sockets, the return value 0 means the peer has closed its half     side of the connection.

那么,你收到了多少字节?如果您丢弃 recv() 的结果,则无法判断。也许 recv() 失败了,如果不检查返回值,你永远不会发现。也许它只填满了你缓冲区的一部分。 您必须检查 recv() 的返回码。这是人们在编写使用 TCP 的程序时犯的第一个错误。

您需要更改代码以处理以下情况:

  1. recv() 调用可能会完全填满您的缓冲区。

  2. recv() 调用可能会部分填充您的缓冲区。

  3. recv() 调用可能会返回 0,表示发送方已关闭连接。

  4. recv() 调用可能指示 EINTR,因为它被系统调用中断了。

  5. recv() 调用可能指示 ECONNRESET,因为发送方突然关闭了连接或消失了。

  6. recv() 调用可能会遇到一些其他错误。

请记住:使用 TCP 时,仅仅因为您 send() 16 个字节并不意味着其他对等方将 recv() 16 个字节——它可能会损坏成 block 。 TCP是一种流协议(protocol)。与 UDP 不同,相邻的数据 block 可以任意连接或拆分。

关于c++ - 在 C++ 中通过套接字传输数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14061847/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com