从插座读取直到我得到足够的字节

发布于 2025-01-19 02:02:04 字数 1665 浏览 0 评论 0原文

我正在尝试阅读一个整数,该整数将使服务器知道消息长度。我会阅读,直到使用while循环到达sizeof(int)字节。我正在遵循同一惯例的惯例和长度使用段循环多次调用RECV。如果我要做的就是阅读int,我可以直接致电recv并期待所有字节吗?

如果没有,那么我应该如何使用一段时间循环在整数中读取。

struct CONN_STAT {
    int size;      // length function should return the length into this field
    int nRecv;     // bytes sent of message
    int nSent;     // bytes received of message
    int lRecv;     // bytes received of length 
    int lSent;     // bytes received of length 
};

服务器:我如何读取长度

我从消息函数中复制逻辑,它读取的逻辑与此相似 但是信息被一个char数组替换,而(info + pstat-> lrecv)为此作用着它

int readLength(int sockfd, int * info, struct CONN_STAT * pStat){

    int infoSize = sizeof(int);

    // I copied the logic from my message function it reads similar to this 
    // but info is replaces by a char array and the (info + pStat->lRecv) works for
    while(pStat->lRecv < infoSize){
        int n = recv(sockfd, info + pStat->lRecv, infoSize - pStat->lRecv, 0);

        if (n > 0) {
            pStat->lRecv += n;
        }
        else if (n == 0 || (n < 0 && errno == ECONNRESET)) {
            close(sockfd);
            return -1;
        }else if (n < 0 && (errno == EWOULDBLOCK)) { 
            //The socket becomes non-readable. Exit now to prevent blocking. 
            //OS will notify us when we can read
            return 0; 
        }else {
            printf("Unexpected recv error.");
        }

    }

    return 0;
}

像此错误一样称呼它

readLength(sockfd, (int*)pStat->size, pStat);

:警告:从较小的整数类型'int'[-wint to-wint-to-pointer)施放到'int *' -投掷]

I'm trying to read in an integer which is going to let the server know the message length. I read until I reach sizeof(int) bytes using a while loop. I'm following the same convention for the message and length using a while loop to call recv multiple times. If all I'm doing is reading a int can I just call recv directly and expect all the bytes?

If not then how should I read in a integer using a while loop.

struct CONN_STAT {
    int size;      // length function should return the length into this field
    int nRecv;     // bytes sent of message
    int nSent;     // bytes received of message
    int lRecv;     // bytes received of length 
    int lSent;     // bytes received of length 
};

server : How I'm reading length

I copied the logic from my message function it reads similar to this
but info is replaced by a char array and the (info + pStat->lRecv) works for it

int readLength(int sockfd, int * info, struct CONN_STAT * pStat){

    int infoSize = sizeof(int);

    // I copied the logic from my message function it reads similar to this 
    // but info is replaces by a char array and the (info + pStat->lRecv) works for
    while(pStat->lRecv < infoSize){
        int n = recv(sockfd, info + pStat->lRecv, infoSize - pStat->lRecv, 0);

        if (n > 0) {
            pStat->lRecv += n;
        }
        else if (n == 0 || (n < 0 && errno == ECONNRESET)) {
            close(sockfd);
            return -1;
        }else if (n < 0 && (errno == EWOULDBLOCK)) { 
            //The socket becomes non-readable. Exit now to prevent blocking. 
            //OS will notify us when we can read
            return 0; 
        }else {
            printf("Unexpected recv error.");
        }

    }

    return 0;
}

Calling it like this

readLength(sockfd, (int*)pStat->size, pStat);

error: warning: cast to 'int *' from smaller integer type 'int' [-Wint-to-pointer-cast]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

給妳壹絲溫柔 2025-01-26 02:02:04

如果我要做的就是阅读int,我可以直接致电recv并期待所有字节吗?

一般来说,不。 TCP是A byte-streaming 协议,因此,它不能保证任何一个呼叫recv()将传递多少个字节。完全有可能(因此,如果有足够的时间,不可避免的),您将recv()仅来自给定的recv()呼叫,而整数的第一部分和您需要将收到的字节保存到某个地方的缓冲区中,并计划以后将其余的字节附加到该缓冲区。您只能在收集用来表示它的整个字节后实际分析/使用收到的整数。

如果不是,那么我应该如何使用while循环在整数中读取。

几乎与您(大概)在整数之后的数据付费中读取的方式几乎相同:将任何接收的字节写入数组中,直到数组中具有解析其所需的字节数为止。 (在这种情况下,您需要在数组中具有sizeof(int)字节,然后才能将整数读为整数...并且不要忘记sizeof(int)< /代码>在不同的计算机上可能是一个不同的值,并且int可以以大型或小型形式表示。而不是inthtonl()ntohl()处理任何必要的endian-contression),

因为您使用了非块/o,我建议将您的收集撤离器放入conn_stat struct,以便给定调用readlength()可以使用任何接收到的字节更新数组,然后再进行后续。呼叫可以更新数组,依此类推。

我想到的方式就是将其视为接收两个数据缓冲器:我可以假设的第一个缓冲区的大小 - 始终是sizeof(int) bytes长。第二个缓冲区我将在收到整个第一个缓冲区并可以阅读包含的内容后立即知道。因此,我可以在两个缓冲区中使用(几乎)相同的逻辑,然后根据需要重复。

If all I'm doing is reading a int can I just call recv directly and expect all the bytes?

Generally speaking, no. TCP is a byte-streaming protocol, so it doesn't guarantee anything about how many bytes will be delivered by any one call to recv(). It's entirely possible (and therefore, given enough time, inevitable) that you'll recv() only the first part of the integer from a given recv() call, and you'll need to save the bytes you've received into a buffer somewhere and plan to append the rest of the bytes to that buffer later on. You can only actually parse/use the received integer after you've collected the whole set of bytes that were used to represent it.

If not then how should I read in a integer using a while loop.

Pretty much the same way you are (presumably) reading in the data-payload that follows the integer: write any received bytes into an array until the array has the number of bytes in it that are required to parse it. (In this case, you need to have sizeof(int) bytes in your array before you can read the integer as an integer... and don't forget that sizeof(int) may be a different value on different machines, and that an int may be represented in either big-endian or little-endian form. You might want to use int32_t instead of int, and htonl() and ntohl() to handle any necessary endian-conversion)

Since you're using non-blocking I/O, I suggest putting your collection-buffer into the CONN_STAT struct, so that a given call to readLength() can update the array with any received bytes and then a subsequent call can update the array some more, and so on.

The way I think about is to just see it as receiving two data-buffers: The first buffer I can assume the size of -- it will always be sizeof(int) bytes long. The second buffer I will know the size of as soon as I have received the entire first buffer and can read what it contains. So I can use (almost) the same logic for both of the two buffers, and then repeat as necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文