关于发送/接收的问题
套接字编程新手。有几个问题:
我的程序与其输出确实不一致。有时我的客户会收到,有时则不会。我每次也使用相同的输入。
只需确认:接收的字节数是否可以小于服务器发送的字节数?
如何才能在获得所需的所有字节后停止接收?
有没有办法让客户端知道它“将”接收多少字节,以便我可以将recv放入while循环中?
感谢大家的时间:) 在 C++ 中执行此操作/非阻塞(如果这很重要的话)。
New to socket programming. Got a couple questions:
My program is really inconsistent with its output. Sometimes my client receives, sometimes it doesnt. I am also using the same input each time.
Just need confirmation: Can the number of bytes received be less than the number of bytes sent from the server?
How do I make it so that I stop receiving once I have all the bytes I need?
Is there a way for a client to know how much bytes it is "going" to receive so that I may put the recv in a while loop?
Thanks for everyones time :) Doing this in C++ / non blocking if that matters at all.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
假设这是 TCP(不是 UDP),您可以将套接字视为字节流。发件人可以按照他想要的任何方式将它们放入,而您也可以按照您想要的任何方式将它们取出。因此,发送方可以在一次调用中写入 1k 块,如果需要,您可以一次接收一个字节。
方法有很多种,但这里有两种相当简单的方法:
您可以使用 select 来告诉您那里是否有任何内容,但它不会告诉您有多少。请参阅问题 2。
Assuming this is TCP (not UDP), you can think of the socket as a stream of bytes. The sender can put them in in whatever way he wants, and you can get them out in whatever way you want. So the sender could write a 1k chunk in one call, and you can receive them a byte at a time if you want.
There are a number of ways, but here are two fairly simple ones:
You can use select to tell you whether there is anything there, though it doesn't tell you how much. See question 2.
使用 recv() 和非阻塞,系统将在您进行调用时为您提供当前可用的任何字节数(最多为您提供的缓冲区的大小)。
因此,如果您的发送方发送 4K 数据,这将通过 IP 流分成更小的数据包,如果您在第一个数据包到达时调用 recv(),您将只能得到该数据包(其余数据将到达)毫秒或秒后,具体取决于网络的延迟)。随后对 recv() 的调用将不会获得任何数据、部分或全部剩余数据(取决于网络计时、缓冲等)。
另外(使用非阻塞 IO)recv() 可以返回 EAGAIN 的 rc,这意味着此时没有可用数据。在这种情况下,通常您会调用 select() 来等待某些内容可用,然后再次调用 receive()。
这个调用也可能有帮助:
这个调用预先检查有多少字节可供读取,因此当您随后调用 recv() 时,您将至少获得这个字节数(假设您提供给 recv() 的缓冲区很大)足够的)。
关于如何停止的问题:
通常对于 IP 流上的数据,有一种方法可以判断消息是否完整。例如,对于许多 RFC 通信(例如与邮件服务器或 http 服务器通信),命令以 \n 终止,因此如果您收到数据并且其中没有 \n,您将继续阅读,因为应该还有更多。
在其他形式中,数据的开头将通过某种方式告诉您后面将有多少数据。 HTTP 请求的标头具有大小字段,或者当通过 SOCKS 代理建立连接时,请求和返回数据包具有定义的长度。在这种情况下,您可以循环直到拥有足够数量的数据(或直到连接失败)。
但这实际上是定义流协议的问题,即发送方和接收方必须就如何发送数据建立某种协议。 IMAP 服务器读取直到 \n 的命令并处理它们,打印服务器可能会读取所有数据,直到连接终止(recv() 因 rc<0 失败),而另一个协议可能只是前两个字节作为长度字段来告诉接下来有多少数据。
With recv() and nonblocking the system will give you whatever number of bytes are currently available when you make the call (up to the size of the buffer which you provide).
So, if your sender for example sends 4K, this will be broken into smaller packets over the IP stream and if your call to recv() happens when just the first packet has arrived you will only get that (the rest of the data will arrive milliseconds or seconds later, depending on the latency of the network). Subsequent calls to recv() will then get none, some or all the rest of the data (depending on network timing, buffering, etc.).
Also (with non blocking IO) recv() can come back with an rc of EAGAIN which means no data is available at this point. In that case usually you use a call to select() to wait until something is available and call recv() again.
What may also help is this call:
This call checks upfront how many bytes are available for read, so when you subsequently call recv() you will be served at least this number of bytes (assuming the buffer you provide to recv() is large enough).
Regarding your question on how to stop:
Usually with data over an IP stream, there is a way to tell if the message is complete. E.g. with many RFC communications (e.g. talking to a mail server or http server) commands are terminated with \n so if you receive data and there's no \n in it, you continue to read because there's supposed to be more.
In other forms the beginning of the data will have some way of telling you how much data will follow. Headers for HTTP requests have a size field or when making a connection over a SOCKS proxy, the request and return packets have defined lenghts. In such caes you can loop until you have that amount data (or until the connection fails).
But that is really a matter of defining the protocol on the stream, i.e. the sender and receiver must establish some sort of agreement how data is sent. An IMAP server reads commands up to \n and processes them, a print server might read all data until the connection is terminated (recv() failing with an rc<0) and another protocol may just first two bytes as a length field to tell how many data will follow.