This is the mail archive of the cygwin@sources.redhat.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: socket read()/write() problem in 1.1.6


On Friday 08 December 2000 06:57, Markus Hoenicka wrote:
> With cygwin1.dll 1.1.4 I get:
> $ ./server5a &
> [1] 1003
>
> markus@WUTZ ~/prog/cygnus-b20/socket
> $ server waiting
> ../client3a
> char to server = 123456789
> adding client on fd 4
> server waiting
> serving client on fd 4; ch=123456789<<
> removing client on fd 4; ch=223456789<<
> server waiting
> char from server = 223456789
>
> With 1.1.6 I get:
> $ ./server5a &
> [1] 141
>
> markus@WUTZ ~/prog/cygnus-b20/socket
> $ server waiting
> ../client3a
> char to server = 123456789
> adding client on fd 4
> server waiting
> serving client on fd 4; ch=123456789<<
> removing client on fd 4; ch=223456789<<
> server waiting
> char from server = 2234500000
>
> i.e. only the first write() gets through.

Ok, I had a chance to look into your sources and to examine what's
going on.

AFAICS, the problem is that you rely on the speed of the connection.
The `read' call on the socket returning only 5 bytes while you're
expecting 10 is doing nothing wrong. Let me explain:

The difference between Cygwin <= 1.1.4 and >= 1.1.5 is that socket
connections are treated as `slow' in the earlier versions while they
are treated as `fast' in the later versions. The implication is that
the earlier versions are doing some overhead on the connection which
results in that the TCP service provider has more time to collect the
incoming information on the socket.

So, when the `read' call in your code is running, the server had
already time to send both 5 bytes packages. In the newer
implementation, the overhead is stripped from the socket `read' call
so the `read' is much faster than before. `read' calls `recv' in turn
and that `recv' call is executed more or less immediately. So, when
the server sends it's 5 byte package, `recv' (which is a Winsock call,
btw) returns that 5 byte package. That's ok!

If you change the client, so that it performs a `sleep(3)' prior to
calling `read', you will see what I mean.

From the description of `recv' in the MSDN:

"For connection-oriented sockets (type SOCK_STREAM for example), calling
recv will return as much information as is currently available - up to
the size of the buffer supplied."

From the Linux `recv' man page:

"The receive calls normally return any data available, up to the
 requested amount, rather than waiting for receipt of the full
 amount requested."

From the Linux `read' man page:

"On success, the number of bytes read is returned (zero indicates
 end of file), and the file position is advanced by this number. It
 is not an error if this number is smaller than the number of bytes
 requested; this may happen for example because fewer bytes are
 actually available right now (maybe because we were close to
 end-of-file, or because we are reading from a pipe, or from a
 terminal), or because read() was interrupted by a signal."

So, your `read' code should not look like this:

  read(sockfd, chin, 10);

but rather look like that (assuming you expect receiving 10 bytes):

  len = 0;
  do {
    i = read(sockfd, chin + len, 10);
  } while (i > 0 && (len += i) < 10);


Hope, that helps,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Developer                                mailto:cygwin@cygwin.com
Red Hat, Inc.
mailto:vinschen@redhat.com

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]