在TCP中发送/处理部分数据写入

时间:2013-03-15 07:05:58

标签: c networking tcp

所以,我有以下代码在TCP上发送我的数据包。它工作得很好。我只需要测试部分写入。所以我通过将sendbuf设置为1或者如下所示进行黑客攻击来写入1个字节。当我拿一个tcpdump时,除了第一个字节之外它都是不正确的..我做错了什么?

int tmi_transmit_packet(struct tmi_msg_pdu *tmi_pkt, int len, int *written_len)
{
int bytes;

// This works
bytes = write(g_tmi_mgr->tmi_conn_fd, (void*) tmi_pkt, len); 

// This doesn't: 
// bytes = write(g_tmi_mgr->tmi_conn_fd, (void*) tmi_pkt, 1); 

if (bytes < 0) {
    if (errno == EAGAIN) {
        return (TMI_SOCK_FULL);
    }
    return (TMI_WRITE_FAILED);
} else if (bytes < len) {
    *written_len += bytes;
    tmi_pkt += bytes;
    return (tmi_transmit_packet(tmi_pkt, len - bytes, written_len));
} else {
    *written_len += len;
}
return TMI_SUCCESS;
}

1 个答案:

答案 0 :(得分:2)

这一行

tmi_pkt += bytes;

最有可能没有达到预期的目的。

它会tmi_pkt增加sizeof(*tmp_pkt) * bytes,而不仅仅是bytes。有关指针算术的好解释,您可能希望click here and have a look at binky

要解决此问题,您可以按如下方式修改代码:

...
else if (bytes < len) {
  void * pv = ((char *) tmp_pkt) + bytes;
  *written_len += bytes;
  return (tmi_transmit_packet(pv, len - bytes, written_len));
}
...

无论如何,这种方式闻起来很脏,因为传递给write函数的指针所指向的数据并不一定需要与它的类型相对应。

因此,更简洁的解决方案是不使用struct tmi_msg_pdu *tmi_pkt,而是使用void *char *作为函数参数声明。

虽然安静奢侈,但这里不需要也不建议使用递归调用。对于大量数据和/或慢速传输,它可能耗尽堆栈存储器。一个简单的循环也可以。后者的优点是你可以使用一个指向缓冲区的临时指针来写入,并且可以坚持使用一个类型化的接口。