关于发送/接收的问题
Posted
技术标签:
【中文标题】关于发送/接收的问题【英文标题】:Question about send / recv 【发布时间】:2009-11-17 23:23:28 【问题描述】:套接字编程新手。有几个问题:
我的程序确实与其输出不一致。有时我的客户收到,有时没有。我每次也使用相同的输入。
只需要确认:接收到的字节数可以小于服务器发送的字节数吗?
如何做到这一点,以便在获得所需的所有字节后停止接收?
有没有办法让客户端知道它“要”接收多少字节,以便我可以将 recv 置于 while 循环中?
感谢大家的时间 :) 在 C++ 中执行此操作/非阻塞,如果这很重要的话。
【问题讨论】:
【参考方案1】:假设这是 TCP(不是 UDP),您可以将套接字视为字节流。发件人可以以他 想要的任何方式将它们放入,您也可以以您 想要的任何方式取出它们。所以发送者可以在一次调用中写入一个 1k 的块,如果你愿意,你可以一次接收一个字节。
有很多方法,但这里有两种相当简单的方法:
如果发送方在发送完所有数据后关闭套接字,接收方将接收到所有发送的数据,下一次调用recv返回0,表示没有什么可接收的了。这就是 HTTP/1.0 的工作原理。 您可以更改您的协议以发送某种包含您将要发送的数据长度的标头,然后recv 将知道需要多少字节。使用 Content-length 标头,这就是 HTTP/1.1 的工作方式(嗯,在大多数情况下)。您可以使用 select 来告诉您那里是否有任何东西,尽管它不会告诉您有多少。见问题 2。
【讨论】:
【参考方案2】:使用 recv() 和非阻塞,系统将在您进行调用时为您提供当前可用的字节数(最多为您提供的缓冲区大小)。
因此,例如,如果您的发件人发送 4K,这将通过 IP 流被分解为更小的数据包,并且如果您对 recv() 的调用仅在第一个数据包到达时发生,您只会得到它(其余的数据将在几毫秒或几秒后到达,具体取决于网络的延迟)。随后对 recv() 的调用将不会得到任何数据、部分或全部数据(取决于网络时间、缓冲等)。
此外(使用非阻塞 IO)recv() 可以返回 EAGAIN 的 rc,这意味着此时没有可用的数据。在这种情况下,您通常会调用 select() 来等待某些内容可用,然后再次调用 recv()。
这个电话也可能有帮助:
int err, avail= 0;
err= soioctl(skt FIONREAD, (char*)&avail);
此调用会预先检查有多少字节可供读取,因此当您随后调用 recv() 时,您将至少获得这个字节数(假设您提供给 recv() 的缓冲区足够大)。
关于如何停止的问题:
通常对于通过 IP 流传输的数据,有一种方法可以判断消息是否完整。例如。许多 RFC 通信(例如,与邮件服务器或 http 服务器通信)命令以 \n 终止,因此如果您收到数据但其中没有 \n,您继续阅读,因为应该有更多。
在其他形式中,数据的开头会以某种方式告诉您接下来会有多少数据。 HTTP 请求的标头具有大小字段,或者当通过 SOCKS 代理建立连接时,请求和返回数据包已定义长度。在这种情况下,您可以循环直到获得该数量的数据(或直到连接失败)。
但这实际上是在流上定义协议的问题,即发送者和接收者必须建立某种协议来发送数据。 IMAP 服务器读取最多 \n 的命令并对其进行处理,打印服务器可能会读取所有数据,直到连接终止(recv() 失败,rc
【讨论】:
以上是关于关于发送/接收的问题的主要内容,如果未能解决你的问题,请参考以下文章