Cam*_*lsa 3 c c++ sockets serialization tcp
我目前正在做一个使用网络的项目。我必须发送一个结构
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];
};
Run Code Online (Sandbox Code Playgroud)
我正在尝试使用 TCP 将 struct Packet 从一个套接字发送到另一个套接字。我试过像这样发送我的结构
send(socket, &my_struct, sizeof(my_struct), 0);
Run Code Online (Sandbox Code Playgroud)
但它不起作用所以我试图将我的结构序列化为 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));
}
Run Code Online (Sandbox Code Playgroud)
即使当我在服务器端读取它时客户端 symply 发送 struct Header 数据已损坏 为什么数据已损坏?
客户端发送循环
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());
}
Run Code Online (Sandbox Code Playgroud)
服务器接收循环:(通过 select() 调用函数)
buff = new char[bav];
socket->read(buff, bav);
hexdump("buff", buff, bav);
Run Code Online (Sandbox Code Playgroud)
套接字->读取():
int TcpSocket::read(char *buff, int len)
{
int ret;
ret = recv(this->_socket, buff, len, 0);
return (ret);
}
Run Code Online (Sandbox Code Playgroud)
当我运行这些程序时:
./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
Run Code Online (Sandbox Code Playgroud)
所以,这是错误的,它肯定会导致错误。
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);
}
Run Code Online (Sandbox Code Playgroud)
recv()不能忽略from 的返回值。来自man 2 recv:
返回值
这些调用返回接收到的字节数,如果有错误,则返回 -1
发生了。
对于 TCP 套接字,返回值 0 表示对等方已关闭其一半
连接的一侧。
那么,您收到了多少字节?无法判断,如果您丢弃recv(). 也许recv()失败了,如果不检查返回值,你永远不会发现。也许它只填满了你的缓冲区的一部分。 您必须从 中检查返回代码recv()。 这是人们在编写使用 TCP 的程序时犯的第一个错误。
您将需要更改代码以处理以下情况:
该recv()调用可能会完全填满您的缓冲区。
该recv()调用可能会部分填满您的缓冲区。
该recv()呼叫可能返回0,表示发送方已经关闭了连接。
该recv()调用可能表明EINTR它被系统调用中断。
该recv()呼叫可能表明ECONNRESET因为发件人突然关闭了连接或已消失。
该recv()呼叫可能会遇到一些其他错误。
请记住:当使用 TCP 时,仅仅因为您有send()16 个字节并不意味着另一个对等方将有recv()16 个字节——它可能被分解成块。TCP 是一种流协议。与 UDP 不同,相邻的数据块可以任意连接或拆分。
| 归档时间: |
|
| 查看次数: |
2478 次 |
| 最近记录: |