0

我正在从这样初始化的套接字中读取字节:

fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));

但是,当我从这个套接字读取

char buf[ETH_FRAME_LEN]
len = read(fd, buf, sizeof(buf));

len 显示只读取了 1500 个字节。我检查了wireshark,返回的数据包是5854。IP下的总长度字段为5840(所以+ 14字节的以太网头= 5854)。我尝试使用更大的缓冲区(6000),但仍然只有 1500 个字节被从线路中读取。

我尝试从服务器请求一个较小的文件(1504 字节),但我得到了相同的结果。由于它是一个原始套接字,因此读入的数据包括以太网标头,因此它不会将最后 4 个字节读入缓冲区。

这可能是什么原因?我不知道有任何论据socket()可能导致这种情况。

4

3 回答 3

1

如果您read再次尝试呼叫会发生什么?消息的下一个块是否很快返回?

从阅读手册页(我的重点)

read() 尝试读取最多count 个字节

如果你想读取一定数量的字节,你应该准备好read循环调用,直到你收到你的目标总数。

于 2012-12-11T11:52:53.083 回答
1

正在发生的事情是,每次调用read().

于 2012-12-11T11:57:12.807 回答
1

read()返回:

成功时,返回读取的字节数(零表示文件结束),文件位置提前该数字。 如果此数字小于请求的字节数,则不是错误;这可能会发生,例如因为现在实际可用的字节数较少(可能是因为我们接近文件结尾,或者因为我们正在从管道或终端读取),或者因为 read() 被中断信号。出错时,返回 -1,并适当设置 errno。在这种情况下,未指定文件位置(如果有)是否更改。

您可以尝试使用recv()MSG_WAITALL不是 pure read()

此标志请求操作阻塞,直到满足完整请求。但是,如果捕获到信号、发生错误或断开连接,或者要接收的下一个数据与返回的类型不同,则调用返回的数据仍可能少于请求的数据。

len = recv(fd, buf, sizeof(buf), MSG_WAITALL);

另一种方法是在循环中读取或接收,例如:

ssize_t Recv(int fd, void* buf, ssize_t n)
{
    ssize_t read = 0;
    ssize_t r;
    while(read != n)
    {
        r = recv(fd, ((char*)buf)+read, n-read, 0);
        if(r == -1)
            return (read) ? read : -1;
        if(r == 0)
            return 0;

        read += r;
    }

    return read;
}
于 2012-12-11T12:17:03.020 回答