如何发送具有不同元素大小的TCP缓冲区?

时间:2016-10-29 20:59:33

标签: c++ tcp

我正在尝试在TCP服务器和客户端之间发送24位消息。

所以我有

uint8_t id = 5;
unint16_t num = 4000;

那么在TCP缓冲区中发送它们的方法是什么?我知道我需要将uint16_t转换为网络字节顺序,我不需要为uint8_t执行此操作。

我发送的消息必须能够与其中一个呼叫一起取消

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

客户端期望一条消息由一个8位字符后跟一个16位数字组成。我无法改变这一点,所以我必须解决一些问题。客户端也将使用上述功能转换消息。

据我所知,使用一个缓冲区无法做到这一点。我看了些什么吗?

4 个答案:

答案 0 :(得分:4)

您可以将数据复制到一个扁平的字节缓冲区中来编组数据,如下所示:

uint8_t id = 5;
uint16_t num = 4000;
uint16_t beVal16 = htons(num);
unsigned char flatbuf[sizeof(id)+sizeof(beVal16)];
memcpy(&flatbuf[0], &id, sizeof(id));
memcpy(&flatbuf[sizeof(id)], &beVal16, sizeof(beVal16));
int numBytesSent = send(theSocketFD, flatbuf, sizeof(flatbuf), 0);

...然后在接收方做相反的事情:

uint8_8 id;
uint16_t beVal16;
unsigned char flatbuf[sizeof(id)+sizeof(beVal16)];
int numBytesReceived = recv(theSocketFD, flatbuf, sizeof(flatbuf), 0);
if (numBytesReceived == sizeof(flatbuf))
{
   memcpy(&id, &flatbuf[0], sizeof(id));
   memcpy(&beVal16, &flatbuf[sizeof(id)], sizeof(beVal16));
   uint16_t num = ntohs(beVal16);

   printf("received num=%u id=%u\n", num, id);
}
else {/* handle error or partial-buffer-receive, omitted here */}

答案 1 :(得分:1)

您可以将数据放在一个缓冲区中,如下所示:

uint8_t id = 5;
unint16_t num = 4000

...
uint8_t buf[3];
buf[0] = id;
//pack num in network byte order:
buf[1] = (num & 0xff00) >> 8;
buf[2] = num & 0xff;

int rc = write(tcpsock, buf, sizeof buf);
//check rc

或者你也可以用它完成它,但效率稍差 因为它执行两次写调用:

int rc = write(tcpsock, &id, sizeof id);
int num_net = htons(num);
rc = write(tcpsock, &num_net sizeof num_net);

答案 2 :(得分:1)

  

客户端期望一条消息由一个8位字符后跟一个16位数字组成。

TCP是一种流式传输,它没有消息概念。您可以单独发送两个值:

uint8_t id = 5;
send(sckt, &id, sizeof(id), 0);

uint16_t num = htons(4000);
send(sckt, &num, sizeof(num), 0);

对等体将以正确的顺序接收3个字节。这是由TCP保证的。接收器可以读取1个字节后跟2个字节,或者一次读取3个字节,或者甚至读取1个字节三次。 TCP不关心。

  

据我所知,使用一个缓冲区无法做到这一点。

当然可以。

对于初学者,如果启用了通过Nagle algorithm发送合并(默认情况下),则套接字将缓冲小发送并以更高效的数据包发送它们。因此,上面的两个send调用很可能会一起传输。

但是,如果您不想依赖它,您只需定义struct来保存值,然后发送:

#pragma pack(push, 1) // or equivalent
struct pktmsg
{
    uint8_t id;
    uint16_t num;
};
#pragma pack(pop)

pktmsg msg;
msg.id = 5;
msg.num = htons(4000);
send(sckt, &msg, sizeof(msg), 0);

答案 3 :(得分:0)

您可以使用 var x0, y0; var dragstart = function(event) { var that = this; var pos = coordinates(event); x0 = pos.x; y0 = pos.y; that.points = []; }; var dragging = function(event) { var that = this; var xy = coordinates(event); var points = that.points; var x1 = xy.x, y1 = xy.y, dx = x1 - x0, dy = y1 - y0; if (dx * dx + dy * dy > 100) { xy = { x: x0 = x1, y: y0 = y1 }; } else { xy = { x: x1, y: y1 }; } points.push(xy); }; 执行此操作,“收集写入”#39;调用