Socket question?

Socket question?

Post by Dave Smit » Sat, 10 Aug 1996 04:00:00



If this question is in the wrong group, then
let me know where it should be posted.

I am communicating between 2 SGI's using
  sockfd = socket(AF_INET, SOCK_STREAM, 0)

My main question is why is the communications so slow?
Especially in the following paradigm.

First I create the sockets and make a connection
all of which is done successfully.

I then proceed into a while loop

while ( 1 )
{
   ...
   ClientOrServerRW();
   ...

Quote:}

if your process is the server then:
ClientOrServerRW() = ServerWriteRead()
whose code is:

ServerWriteRead()
{
   write( sockfd, &data_set1, datasize );
   read( sockfd, &data_set2, datasize  );

Quote:}

if your process is the client then:
ClientOrServerRW() = ClientReadWrite()
whose code is:

ClientReadWrite()
{
   read( sockfd, &data_set2, datasize  );
   write( sockfd, &data_set1, datasize );

Quote:}

This process seems to work somewhat well,
the communication speed is acceptable, not preferable.

But when I add one more write to ServerWriteRead()
and one more read to ClientReadWrite(),
the communications almost comes to a complete hault.
Why?

What is even more strange is that when I bring this
up in the de* it seems most of the time is spent
on the first read ( on the Server side ).
Why?

I tried a non-blocking read/write method but this didn't
seem to help.  To set non-blocking, I made this call:

    ioctl ( sockfd, O_NONBLOCK, 1 );
Would this be the correct way to set non-blocking?

Please feel free to attack the method of communicating
if it is inefficient.  I would like to know.
Keep in mind that the goal I am trying to achieve
is constant, up-to-date data between the Client and Server.
(Example: (x,y) coordinate pairs that are on the Client side
          in which the Server should know and vice-versa.)

Any help is greatly appreciated,

 -DaveS

===========================================================================

| Product Development -- Feature Based      |  513-576-2601 (Voice)       |
|                        Applications       |  513-576-???? (FAX)         |
| Structural Dynamics Research Corporation  |                             |
| 2000 Eastman Drive                        |          ?                  |
| Milford, OH  45150                        |                             |

 
 
 

Socket question?

Post by Andrew Gier » Sun, 11 Aug 1996 04:00:00


Quote:>>>>> "Dave" == Dave Smith <gedavesm> writes:

 Dave> If this question is in the wrong group, then
 Dave> let me know where it should be posted.

Er:
        comp.unix.programmer:  ideal.
        comp.unix.internals:   no (you are writing *user* code)
        comp.protocols.tcp-ip: maybe (touches on a protocol issue)
        comp.client-server:    don't know (I don't read it)
        comp.lang.c:           no; expect the usual flame :-)
        comp.sys.sgi.misc:     the problem isn't really SGI specific, but
                               you weren't to know that.

Followups in comp.unix.programmer only.

 Dave> I am communicating between 2 SGI's using
 Dave>   sockfd = socket(AF_INET, SOCK_STREAM, 0)

 Dave> My main question is why is the communications so slow?
 Dave> Especially in the following paradigm.
[code snipped]
 Dave> This process seems to work somewhat well,
 Dave> the communication speed is acceptable, not preferable.

 Dave> But when I add one more write to ServerWriteRead()
 Dave> and one more read to ClientReadWrite(),
 Dave> the communications almost comes to a complete hault.
 Dave> Why?

Well, offhand, it is generally a bad move to do multiple small successive
write() calls to a TCP socket, because the Nagle algorithm kicks in at
that point. There's an explanation in the sockets FAQ (see below).

 Dave> I tried a non-blocking read/write method but this didn't
 Dave> seem to help.  To set non-blocking, I made this call:

 Dave>     ioctl ( sockfd, O_NONBLOCK, 1 );
 Dave> Would this be the correct way to set non-blocking?

No.

Either:
           int flags = fcntl(sockfd, F_GETFL, 0);
           fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
or:
           int i = 1;
           ioctl(sockfd, FIONBIO, &i);

You've confused the two.

Your next port of call should be the unix-socket-faq, regularly posted
to comp.unix.programmer and comp.answers, and also available from:

  http://www.auroraonline.com/sock-faq
  http://kipper.york.ac.uk/~vic/sock-faq
  ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/socket

Hope this helps.

--


 
 
 

Socket question?

Post by Ron McOu » Sun, 11 Aug 1996 04:00:00


[snip]

Quote:>while ( 1 )
>{
>   ...
>   ClientOrServerRW();
>   ...
>}
>if your process is the server then:
>ClientOrServerRW() = ServerWriteRead()
>whose code is:
>ServerWriteRead()
>{
>   write( sockfd, &data_set1, datasize );
>   read( sockfd, &data_set2, datasize  );
>}
>if your process is the client then:
>ClientOrServerRW() = ClientReadWrite()
>whose code is:
>ClientReadWrite()
>{
>   read( sockfd, &data_set2, datasize  );
>   write( sockfd, &data_set1, datasize );
>}
>This process seems to work somewhat well,
>the communication speed is acceptable, not preferable.
>But when I add one more write to ServerWriteRead()
>and one more read to ClientReadWrite(),
>the communications almost comes to a complete hault.
>Why?
>What is even more strange is that when I bring this
>up in the de* it seems most of the time is spent
>on the first read ( on the Server side ).
>Why?
>I tried a non-blocking read/write method but this didn't
>seem to help.  To set non-blocking, I made this call:

>    ioctl ( sockfd, O_NONBLOCK, 1 );
>Would this be the correct way to set non-blocking?
>Please feel free to attack the method of communicating
>if it is inefficient.  I would like to know.
>Keep in mind that the goal I am trying to achieve
>is constant, up-to-date data between the Client and Server.
>(Example: (x,y) coordinate pairs that are on the Client side
>          in which the Server should know and vice-versa.)

The main problem I have here with write-read on one side and
read-write on the other is you have to always pair the I/O operations.

I would use a select() statement and then handle the read of the
socket on an as needed basis.  All your other inputs / outputs that
are external in nature (user interface devices) would need to be in
the same select.  If you have a compute loop you have to keep running
between the socket I/O then the select could have a short timer on it
and you look with the select at appropriate intervals.

You do not mention the data sizes sent on the read / write.  The CPU
load of the TCP/IP wrappers and the layer 2 wrappers for ethernet
encapsulation plus data padding to a minimum ethernet packet size of
60 bytes on the wire will lead to disappointing throughputs for short
packets.  Also you don't mention how many other systems are connected
to the same LAN segment.  To get close to media speed you have to have
an isolated LAN segment for the two machines or at least no traffic on
the other machines and large packets that generate maximum MTU size
LAN packets (~1500 for ethernet 4K for fddi).

- Show quoted text -

>Any help is greatly appreciated,
> -DaveS
>===========================================================================

>| Product Development -- Feature Based      |  513-576-2601 (Voice)       |
>|                        Applications       |  513-576-???? (FAX)         |
>| Structural Dynamics Research Corporation  |                             |
>| 2000 Eastman Drive                        |          ?                  |
>| Milford, OH  45150                        |                             |

 
 
 

Socket question?

Post by Steven Laws » Tue, 13 Aug 1996 04:00:00


Let's not forget the next problem he is going to encounter (haven't
we all?), and that is:  Since there is no looping read, one day the
data structure won't be completely filled in and he'll wonder why.
Might as well touch on that up front then.  Since TCP is a stream and
does not preserve record boundaries you need to be prepared to get
back less data than you request in a single read.  And the best part
is it will appear to work fine as-is until you throw a router or two at it.



> [snip]
> >while ( 1 )
> >{
> >   ...
> >   ClientOrServerRW();
> >   ...
> >}
> >if your process is the server then:
> >ClientOrServerRW() = ServerWriteRead()
> >whose code is:
> >ServerWriteRead()
> >{
> >   write( sockfd, &data_set1, datasize );
> >   read( sockfd, &data_set2, datasize  );
> >}
> >if your process is the client then:
> >ClientOrServerRW() = ClientReadWrite()
> >whose code is:
> >ClientReadWrite()
> >{
> >   read( sockfd, &data_set2, datasize  );
> >   write( sockfd, &data_set1, datasize );
> >}
> >This process seems to work somewhat well,
> >the communication speed is acceptable, not preferable.
> >But when I add one more write to ServerWriteRead()
> >and one more read to ClientReadWrite(),
> >the communications almost comes to a complete hault.
> >Why?
> >What is even more strange is that when I bring this
> >up in the de* it seems most of the time is spent
> >on the first read ( on the Server side ).
> >Why?
> >I tried a non-blocking read/write method but this didn't
> >seem to help.  To set non-blocking, I made this call:

> >    ioctl ( sockfd, O_NONBLOCK, 1 );
> >Would this be the correct way to set non-blocking?
> >Please feel free to attack the method of communicating
> >if it is inefficient.  I would like to know.
> >Keep in mind that the goal I am trying to achieve
> >is constant, up-to-date data between the Client and Server.
> >(Example: (x,y) coordinate pairs that are on the Client side
> >          in which the Server should know and vice-versa.)
> The main problem I have here with write-read on one side and
> read-write on the other is you have to always pair the I/O operations.
> I would use a select() statement and then handle the read of the
> socket on an as needed basis.  All your other inputs / outputs that
> are external in nature (user interface devices) would need to be in
> the same select.  If you have a compute loop you have to keep running
> between the socket I/O then the select could have a short timer on it
> and you look with the select at appropriate intervals.
> You do not mention the data sizes sent on the read / write.  The CPU
> load of the TCP/IP wrappers and the layer 2 wrappers for ethernet
> encapsulation plus data padding to a minimum ethernet packet size of
> 60 bytes on the wire will lead to disappointing throughputs for short
> packets.  Also you don't mention how many other systems are connected
> to the same LAN segment.  To get close to media speed you have to have
> an isolated LAN segment for the two machines or at least no traffic on
> the other machines and large packets that generate maximum MTU size
> LAN packets (~1500 for ethernet 4K for fddi).
> >Any help is greatly appreciated,
> > -DaveS
> >===========================================================================

> >| Product Development -- Feature Based      |  513-576-2601 (Voice)       |
> >|                        Applications       |  513-576-???? (FAX)         |
> >| Structural Dynamics Research Corporation  |                             |
> >| 2000 Eastman Drive                        |          ?                  |
> >| Milford, OH  45150                        |                             |

 
 
 

Socket question?

Post by Steve Alexand » Wed, 14 Aug 1996 04:00:00



Quote:>What is even more strange is that when I bring this
>up in the de* it seems most of the time is spent
>on the first read ( on the Server side ).

If I had to guess without seeing a packet trace, I would suggest having the
client set the socket option TCP_NODELAY might help your problem, e.g.:

        #include <netinet/tcp.h>
        {
                int on = 1;
                (void) setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char *)&on,
                        sizeof(on));
        }

--
Steve Alexander | Silicon Graphics, Inc.     | +1 (415) 933-6172 (Voice)

"Thousands of lives hang in the balance and we're forced to depend on a trained
monkey."