gpt4 book ai didi

c - ntohs() 问题 : Write Integer in C socket

转载 作者:太空宇宙 更新时间:2023-11-04 02:32:22 24 4
gpt4 key购买 nike

我正在尝试将整数值写入/从 C 套接字读取。有时 ntohs() 会返回非常大的值,例如 55000 、 32000 等...尽管客户端始终发送值 <1500。如果我运行该程序,它会在 10-15 分钟后发生……有时会在 20-30 分钟后发生。

你能检查下面的代码并告诉我吗为什么要打印这一行?

printf("Garbage value - ntohs problem ..Exiting... ");

// write exactly n byte
inline int write_n(int fd, char *buf, int n) {

int nwrite, left = n;
int totalwrite = 0;

while (totalwrite != n) {
if ((nwrite = write(fd, buf, left)) <= 0) {
break;
} else {
totalwrite = totalwrite + nwrite;
left -= nwrite;
buf += nwrite;
}

}
if (totalwrite == 0)
return nwrite;
return totalwrite;
}

// send exactly n byte
inline int send_n(int fd, char *buf, int n) {

int nwrite, left = n;
int totalwrite = 0;

while (totalwrite != n) {
if ((nwrite = send(fd, buf, left, MSG_NOSIGNAL)) <= 0) {
break;
} else {
totalwrite = totalwrite + nwrite;
left -= nwrite;
buf += nwrite;
}

}
if (totalwrite == 0)
return nwrite;

return totalwrite;
}



uint16_t nread, len, plength, nsend;
int MTU = 1500;
char buffer[2000];

// Server receive ( Linux 64 bit)
while (1) {
// read packet length
nread = read_n(TCP_SOCKFD, (char *) &plength, sizeof(plength));
if (nread <=0) {
break;
}

len = ntohs(plength);
if (len <=0 || len > 1500 ) {
**printf("Garbage value - ntohs problem ..Exiting... "); // WHY ?**
break;
}

// read packat data
nread = read_n(SOCKFD, buffer, len);
if (nread != len) {
break;
}

}

//---------------------
// CLIENT send ( Android 5 )
while (1) {

nread = read(tunfd, buffer, MTU);

if (nread <= 0 || nread > 1500) { // always <=1500
break;
}

plength = htons(nread);
// send packet lenght
nsend = send_n(TCP_SOCKFD, (char *) &plength, sizeof(plength));
if (nsend != sizeof(plength)) {
break;
}
// send packet data
nsend = send_n(TCP_SOCKFD, buffer, nread);
if (nsend != nread) {
break;
}

}

谢谢

最佳答案

我们无法确定地告诉您发生了什么,因为您无法提供可验证的示例。此外,您还没有介绍 read_n() 的实现,但假设它遵循与 write_n()send_n() 相同的模型>,我们仍然可以进行一些分析。

如果数据传输因错误而中断,每个数据传输函数都会返回一个短计数。客户端代码会监视它,如果检测到它就会跳出循环。很好,很好。但是,服务器代码在读取 plength不会执行此操作。由于作为 uint16_tplength 大小为两个字节,因此可以进行部分读取并且不会被服务器代码注意到。

在您的示例中,plength 仅通过出现的一个 read_n() 调用进行修改。网络字节顺序是 big-endian,因此首先读取最高有效字节。该字节与上次读取留下的陈旧字节的组合可能表示一个超过 1500 的数字。例如,如果一个 221(0x00dd) 字节的数据包后面跟着一个 1280(0x0500) 字节的数据包,并且部分读取发生在第二个数据包大小上,则组合结果将为 1501(0x05dd)。

我目前看不出有任何理由认为客户端发送的数据在本质上与您认为的不同,而且我目前看不到任何其他方式可以让您的服务器代码看起来接收的数据与您想象的不同客户端发送,特别是因为客户端和服务器都在第一个识别出的问题迹象时中止。

但是请注意,此代码仍然可以变得更加健壮。特别是考虑到 read()write()send() 可能会失败,即使底层套接字没有问题或数据传输请求。特别是,如果调用被信号中断,它们可能会因 EINTR 而失败,如果套接字处于非阻塞模式,它们可能会因 EAGAIN 而失败。可能还有其他人。在非阻塞模式下操作您的套接字似乎没有用,但您可能确实想要观察 EINTR 并在接收到它后继续读取。

我还建议,至少在开发期间,您应该提供更多关于错误性质的数据。例如,调用 perror(),然后打印错误数据。您甚至可以考虑记录发送和接收的数据。

关于c - ntohs() 问题 : Write Integer in C socket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41622940/

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