我试图将Integer值写入C套接字或从C套接字读取Integer值。有时ntohs()返回非常大的值,例如55000,32000等...尽管客户端始终发送的值
能否请您检查下面的代码并告诉我
为什么要打印此行?


// 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时,服务器代码不会执行此操作。由于plength(作为uint16_t)的大小为2个字节,因此可能会进行部分读取,并且服务器代码不会引起注意。

在您的示例中,仅通过显示的一个plength调用来修改read_n()。网络字节顺序为高位字节序,因此最重要的字节先被读取。该字节与前一次读取剩余的陈旧数据的组合可能代表超过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/

10-11 22:48
查看更多