所以,我有以下代码在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;
}
答案 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 *
作为函数参数声明。
虽然安静奢侈,但这里不需要也不建议使用递归调用。对于大量数据和/或慢速传输,它可能耗尽堆栈存储器。一个简单的循环也可以。后者的优点是你可以使用一个指向缓冲区的临时指针来写入,并且可以坚持使用一个类型化的接口。