简体   繁体   English

有关发送/接收的问题

[英]Question about send / recv

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. 我每次也使用相同的输入。

  1. Just need confirmation: Can the number of bytes received be less than the number of bytes sent from the server? 只需确认一下:接收到的字节数可以小于服务器发送的字节数吗?

  2. How do I make it so that I stop receiving once I have all the bytes I need? 如何获得所有需要的字节后停止接收?

  3. 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? 客户端是否有办法知道要“接收”多少字节,以便我可以将recv放入while循环中?

Thanks for everyones time :) Doing this in C++ / non blocking if that matters at all. 谢谢大家的时间:)如果有问题的话,请使用C ++ /非阻塞进行。

  1. Assuming this is TCP (not UDP), you can think of the socket as a stream of bytes. 假设这是TCP(不是UDP),则可以将套接字视为字节流。 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. 因此,发件人可以在一个呼叫中写入一个1k的块,如果需要,您可以一次接收一个字节。

  2. There are a number of ways, but here are two fairly simple ones: 有很多方法,但是这里有两种非常简单的方法:

    • if the sender closes the socket after sending all of its data, the receiver will receive all the data sent, and the next call to recv will return 0, indicating that there is nothing more to receive. 如果发送方在发送完所有数据后关闭套接字,则接收方将接收所有发送的数据,并且对recv的下一次调用将返回0,表示没有其他接收内容。 This is how HTTP/1.0 works. 这就是HTTP / 1.0的工作方式。
    • You can change your protocol to send some kind of header containing the length of the data you are about to send, and then recv will know how many bytes to expect. 您可以更改协议以发送某种标头,其中包含要发送的数据的长度,然后recv将知道期望多少字节。 With the Content-length header, this is how HTTP/1.1 works (well, for the most part). 使用Content-length标头,这就是HTTP / 1.1的工作方式(大部分情况下是这样)。
  3. You can use select to tell you whether there is anything there, though it doesn't tell you how much. 您可以使用select来告诉您那里是否有任何东西,尽管它并不能告诉您多少。 See question 2. 参见问题2。

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). 使用recv()和非阻塞时,系统将在您进行调用时为您提供当前可用的任意数量的字节(最大为您提供的缓冲区的大小)。

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). 因此,例如,如果您的发送方发送了4K,则它将在IP流上分解为较小的数据包,并且如果仅在第一个数据包到达时才调用recv(),则您只会收到该数据包(其余数据将到达毫秒或秒后,具体取决于网络的延迟)。 Subsequent calls to recv() will then get none, some or all the rest of the data (depending on network timing, buffering, etc.). 随后对recv()的调用将不获取任何,部分或全部其余数据(取决于网络时序,缓冲等)。

Also (with non blocking IO) recv() can come back with an rc of EAGAIN which means no data is available at this point. 同样(使用无阻塞IO),recv()可以返回带有EAGAIN的rc,这意味着此时没有可用数据。 In that case usually you use a call to select() to wait until something is available and call recv() again. 在那种情况下,通常使用对select()的调用来等待直到有可用的东西,然后再次调用recv()。

What may also help is this call: 此调用可能也有帮助:

int err, avail= 0;
err= soioctl(skt FIONREAD, (char*)&avail);

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). 该调用会预先检查可读取的字节数,因此,当您随后调用recv()时,将至少为该字节数提供服务(假设您提供给recv()的缓冲区足够大)。

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. 通常,通过IP流上的数据,有一种方法可以判断消息是否完整。 Eg with many RFC communications (eg 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. 例如,许多RFC通信(例如,与邮件服务器或http服务器交谈)的命令都以\\ n终止,因此,如果您接收到数据并且其中没有\\ n,则您将继续阅读,因为应该有更多内容。

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. HTTP请求的标头具有大小字段,或者在通过SOCKS代理建立连接时,请求和返回数据包已定义长度。 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, ie 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. IMAP服务器最多可读取\\ n命令并对其进行处理,打印服务器可能会读取所有数据,直到连接终止(recv()失败且rc <0),而另一个协议可能只是前两个字节作为长度字段来告知将会跟随多少数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM