精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>网络与通讯>>socket FAQ

主题:socket FAQ
发信人: vmstat()
整理人: mrcloud(2000-08-24 02:06:23), 站内信件
Newsgroups: comp.unix.programmer,comp.unix.answers,comp.answers,news.a
nswers
Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!news.kodak.com!ne
ws-pen-14.sprintlink.net!206.229.87.26!news-east.sprintlink.net!news-p
eer.sprintlink.net!news.sprintlink.net!Sprint!newsfeed.internetmci.com
!206.246.194.8!newsxfer.visi.net!hub.org!news.trends.ca!innuendo.tlug.
org!brutus!vic
From: [email protected] (Vic Metcalfe)
Subject: [comp.unix.programmer] Unix-socket-faq for network programmin
g
Approved: [email protected]
Followup-To: comp.unix.programmer
X-Newsreader: TIN [version 1.2 PL2]
Organization: Zymurgy Systems, Aurora, Ontario, Canada
Message-ID: <[email protected]>
Date: Sun, 22 Mar 1998 12:32:27 GMT
Summary: This posting offers answers to frequent questions about netwo
rk
         programming in the unix environment using sockets.
Lines: 2158
Xref: senator-bedfellow.mit.edu comp.unix.programmer:70708 comp.answer
s:30576 news.answers:126090

Archive-name: unix-faq/socket
Posting-Frequency: monthly
Last-modified: 1998/01/22
URL: http://www.ibrado.com/sock-faq/

  Programming UNIX Sockets in C - Frequently Asked Questions
  Created by Vic Metcalfe, Andrew Gierth and other con-
  tributers
  January 22, 1998

  This is a list of frequently asked questions, with answers about pro
-
  gramming TCP/IP applications in unix with the sockets interface.
  ____________________________________________________________________
__

  Table of Contents:

  1.      General Information and Concepts

  1.1.    About this FAQ

  1.2.    Who is this FAQ for?

  1.3.    What are Sockets?

  1.4.    How do Sockets Work?

  1.5.    Where can I get source code for the book [book title]?

  1.6.    Where can I get more information?

  2.      Questions regarding both Clients and Servers (TCP/SOCK_STREA
M)

  2.1.    How can I tell when a socket is closed on the other end?

  2.2.    What's with the second parameter in bind()?

  2.3.    How do I get the port number for a given service?

  2.4.    If bind() fails, what should I do with the socket descriptor
?

  2.5.    How do I properly close a socket?

  2.6.    When should I use shutdown()?

  2.7.    Please explain the TIME_WAIT state.

  2.8.    Why does it take so long to detect that the peer died?

  2.9.    What are the pros/cons of select(), non-blocking I/O and
  SIGIO?

  2.10.   Why do I get EPROTO from read()?

  2.11.   How can I force a socket to send the data in its buffer?

  2.12.   Where can a get a library for programming sockets?

  2.13.   How come select says there is data, but read returns zero?

  2.14.   Whats the difference between select() and poll()?

  2.15.   How do I send [this] over a socket?

  2.16.   How do I use TCP_NODELAY?

  2.17.   What exactly does the Nagle algorithm do?

  2.18.   What is the difference between read() and recv()?

  2.19.   I see that send()/write() can generate SIGPIPE. Is there any

  advantage to handling the signal, rather than just ignoring it and
  checking for the EPIPE error? Are there any useful parameters passed

  to the signal catching function?

  2.20.   After the chroot(), calls to socket() are failing.  Why?

  2.21.   Why do I keep getting EINTR from the socket calls?

  2.22.   When will my application receive SIGPIPE?

  2.23.   What are socket exceptions?  What is out-of-band data?

  2.24.   How can I find the full hostname (FQDN) of the system I'm
  running on?

  3.      Writing Client Applications (TCP/SOCK_STREAM)

  3.1.    How do I convert a string into an internet address?

  3.2.    How can my client work through a firewall/proxy server?

  3.3.    Why does connect() succeed even before my server did an
  accept()?

  3.4.    Why do I sometimes lose a server's address when using more
  than one server?

  3.5.    How can I set the timeout for the connect() system call?

  3.6.    Should I bind() a port number in my client program, or let t
he
  system choose one for me on the connect() call?

  3.7.    Why do I get "connection refused" when the server isn't
  running?

  3.8.    What does one do when one does not know how much information

  is comming over the socket ? Is there a way to have a dynamic buffer
 ?

  4.      Writing Server Applications (TCP/SOCK_STREAM)

  4.1.    How come I get "address already in use" from bind()?

  4.2.    Why don't my sockets close?

  4.3.    How can I make my server a daemon?

  4.4.    How can I listen on more than one port at a time?

  4.5.    What exactly does SO_REUSEADDR do?

  4.6.    What exactly does SO_LINGER do?

  4.7.    What exactly does SO_KEEPALIVE do?

  4.8.    How can I bind() to a port number < 1024?

4.9. How do I get my server to find out the client's address /
hostname?

4.10. How should I choose a port number for my server?

4.11. What is the difference between SO_REUSEADDR and SO_REUSEPORT
?

4.12. How can I write a multi-homed server?

4.13. How can I read only one character at a time?

4.14. I'm trying to exec() a program from my server, and attach my

socket's IO to it, but I'm not getting all the data across. Why?

5. Writing UDP/SOCK_DGRAM applications

5.1. When should I use UDP instead of TCP?

5.2. What is the difference between "connected" and "unconnected"

sockets?

5.3. Does doing a connect() call affect the receive behaviour of

the socket?

5.4. How can I read ICMP errors from "connected" UDP sockets?

5.5. How can I be sure that a UDP message is received?

5.6. How can I be sure that UDP messages are received in order?

5.7. How often should I re-transmit un-acknowleged messages?

5.8. How come only the first part of my datagram is getting
through?

5.9. Why does the socket's buffer fill up sooner than expected?

6. Advanced Socket Programming

6.1. How would I put my socket in non-blocking mode?

6.2. How can I put a timeout on connect()?

7. Sample Source Code
____________________________________________________________________
__

1. General Information and Concepts

1.1. About this FAQ

This FAQ is maintained by Vic Metcalfe ([email protected]), with lots of
assistance from Andrew Gierth ([email protected]). I am

depending on the true wizards to fill in the details, and correct my

(no doubt) plentiful mistakes. The code examples in this FAQ are
written to be easy to follow and understand. It is up to the reader

to make them as efficient as required. I started this faq because
after reading comp.unix.programmer for a short time, it became evide
nt
that a FAQ for sockets was needed.

The FAQ is available at the following locations:

Usenet: (Posted on the 21st of each month)
news.answers, comp.answers, comp.unix.answers,
comp.unix.programmer

FTP:
ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/socket

WWW:
http://www.ibrado.com/sock-faq
http://kipper.york.ac.uk/~vic/sock-faq http://www.ntua.gr/sock
-
faq

Please email me if you would like to correct or clarify an answer.
I
would also like to hear from you if you would like me to add a
question to the list. I may not be able to answer it, but I can add

it in the hopes that someone else will submit an answer. Every hour
I
seem to be getting even busier, so if I am slow to respond to your
email, please be patient. If more than a week passes you may want t
o
send me another one as I often put messages aside for later and then

forget about them. I'll have to work on dealing with my mail better
,
but until then feel free to pester me a little bit.

1.2. Who is this FAQ for?

This FAQ is for C programmers in the Unix environment. It is not
intended for WinSock programmers, or for Perl, Java, etc. I have
nothing against Windows or Perl, but I had to limit the scope of the

FAQ for the first draft. In the future, I would really like to
provide examples for Perl, Java, and maybe others. For now though I

will concentrate on correctness and completeness for C.

This version of the FAQ will only cover sockets of the AF_INET famil
y,
since this is their most common use. Coverage of other types of
sockets may be added later.

1.3. What are Sockets?

Sockets are just like "worm holes" in science fiction. When things
go
into one end, they (should) come out of the other. Different kinds
of
sockets have different properties. Sockets are either connection-
oriented or connectionless. Connection-oriented sockets allow for
data to flow back and forth as needed, while connectionless sockets

(also known as datagram sockets) allow only one message at a time to

be transmitted, without an open connection. There are also differen
t
socket families. The two most common are AF_INET for internet
connections, and AF_UNIX for unix IPC (interprocess communication).

As stated earlier, this FAQ deals only with AF_INET sockets.

1.4. How do Sockets Work?

The implementation is left up to the vendor of your particular unix,

but from the point of view of the programmer, connection-oriented
sockets work a lot like files, or pipes. The most noticeable
difference, once you have your file descriptor is that read() or
write() calls may actually read or write fewer bytes than requested.

If this happens, then you will have to make a second call for the re
st
of the data. There are examples of this in the source code that
accompanies the faq.

1.5. Where can I get source code for the book [book title]?

Here is a list of the places I know to get source code for network
programming books. It is very short, so please mail me with any
others you know of.

Title: Unix Network Programming
Author: W. Richard Stevens ([email protected])
Publisher: Prentice Hall, Inc.
ISBN: 0-13-949876-1
URL: http://www.noao.edu/~rstevens

Title: Power Programming with RPC
Author: John Bloomer
Publisher: O'Reilly & Associates, Inc.
ISBN: 0-937175-77-3
URL: ftp://ftp.uu.net/published/oreilly/nutshell/rpc/rpc.tar.Z

Recommended by: Lokmanm Merican (lokmanm#[email protected])

Title: UNIX PROGRAM DEVELOPMENT for IBM PC'S Including OSF/Motif
Author: Thomas Yager
Publisher: Addison Wesley, 1991
ISBN: 0-201-57727-5

1.6. Where can I get more information?

I keep a copy of the resources I know of on my socks page on the web
.
I don't remember where I got most of these items, but some day I'll

check out their sources, and provide ftp information here. For now,

you can get them at http://www.ibrado.com/sock-faq.

There is a good TCP/IP FAQ maintained by George Neville-Neil
([email protected]) which can be found at
http://www.visi.com/~khayes/tcpipfaq.html

2. Questions regarding both Clients and Servers (TCP/SOCK_STREAM)

2.1. How can I tell when a socket is closed on the other end?

From Andrew Gierth ([email protected]):

AFAIK:

If the peer calls close() or exits, without having messed with
SO_LINGER, then our calls to read() should return 0. It is less clea
r
what happens to write() calls in this case; I would expect EPIPE, no
t
on the next call, but the one after.

If the peer reboots, or sets l_onoff = 1, l_linger = 0 and then
closes, then we should get ECONNRESET (eventually) from read(), or
EPIPE from write().

I should also point out that when write() returns EPIPE, it also
raises the SIGPIPE signal - you never see the EPIPE error unless you

handle or ignore the signal.

If the peer remains unreachable, we should get some other error.

I don't think that write() can legitimately return 0. read() should

return 0 on receipt of a FIN from the peer, and on all following
calls.

So yes, you must expect read() to return 0.

As an example, suppose you are receiving a file down a TCP link; you

might handle the return from read() like this:

rc = read(sock,buf,sizeof(buf));
if (rc > 0)
  {
      write(file,buf,rc);
      /* error checking on file omitted */
  }
  else if (rc == 0)
  {
      close(file);
      close(sock);
      /* file received successfully */
  }
  else /* rc < 0 */
{
/* close file and delete it, since data is not complete
report error, or whatever */
}

2.2. What's with the second parameter in bind()?

The man page shows it as "struct sockaddr *my_addr". The sockaddr
struct though is just a place holder for the structure it really
wants. You have to pass different structures depending on what kind

of socket you have. For an AF_INET socket, you need the sockaddr_in

structure. It has three fields of interest:

sin_family
Set this to AF_INET.

sin_port
The network byte-ordered 16 bit port number

sin_addr
The host's ip number. This is a struct in_addr, which contain
s
only one field, s_addr which is a u_long.

2.3. How do I get the port number for a given service?

Use the getservbyname() routine. This will return a pointer to a
servent structure. You are interested in the s_port field, which
contains the port number, with correct byte ordering (so you don't
need to call htons() on it). Here is a sample routine:

/* Take a service name, and a service type, and return a port number
. If the
service name is not found, it tries it as a decimal number. The
number
returned is byte ordered for the network. */
int atoport(char *service, char *proto) {
int port;
long int lport;
struct servent *serv;
char *errpos;

/* First try to read it from /etc/services */
serv = getservbyname(service, proto);
if (serv != NULL)
port = serv->s_port;
    else { /* Not in services, maybe a number? */
      lport = strtol(service,&errpos,0);
      if ( (errpos[0] != 0) || (lport < 1) || (lport > 5000) )
        return -1; /* Invalid port address */
      port = htons(lport);
    }
    return port;
  }

  2.4.  If bind() fails, what should I do with the socket descriptor?


  If you are exiting, I have been assured by Andrew that all unixes wi
ll
  close open file descriptors on exit.  If you are not exiting though,

  you can just close it with a regular close() call.

  2.5.  How do I properly close a socket?

  This question is usually asked by people who try close(), because th
ey
  have seen that that is what they are supposed to do, and then run
  netstat and see that their socket is still active.  Yes, close() is

  the correct method.  To read about the TIME_WAIT state, and why it i
s
  important, refer to ``2.7 Please explain the TIME_WAIT state.''.

  2.6.  When should I use shutdown()?

  From Michael Hunter ([email protected]):

  shutdown() is useful for deliniating when you are done providing a
  request to a server using TCP.  A typical use is to send a request t
o
  a server followed by a shutdown().  The server will read your reques
t
  followed by an EOF (read of 0 on most unix implementations).  This
  tells the server that it has your full request.  You then go read
  blocked on the socket.  The server will process your request and sen
d
  the necessary data back to you followed by a close.  When you have
  finished reading all of the response to your request you will read a
n
  EOF thus signifying that you have the whole response.  It should be

  noted the TTCP (TCP for Transactions -- see R. Steven's home page)
  provides for a better method of tcp transaction management.

  S.Degtyarev ([email protected]) wrote a nice in-depth message to 
me
  about this.  He shows a practical example of using shutdown() to aid

  in synchronization of client processes when one is the "reader"
  process, and the other is the "writer" process.  A portion of his
  message follows:

  Sockets are very similar to pipes in the way they are used for data

  transfer and client/server transactions, but not like pipes they are

  bidirectional.  Programs that use sockets often fork() and each
  process inherits the socket descriptor.  In pipe based programs it i
s
  strictly recommended to close all the pipe ends that are not used to

  convert the pipe line to one-directional data stream to avoid data
  losses and deadlocks.  With the socket there is no way to allow one

  process only to send data and the other only to receive so you shoul
d
  always keep in mind the consequences.

  Generally the difference between close() and shutdown() is: close()

  closes the socket id for the process but the connection is still
  opened if another process shares this socket id.  The connection sta
ys
  opened both for read and write, and sometimes this is very important
.
  shutdown() breaks the connection for all processes sharing the socke
t
  id.  Those who try to read will detect EOF, and those who try to wri
te
  will reseive SIGPIPE, possibly delayed while the kernel socket buffe
r
  will be filled.  Additionally, shutdown() has a second argument whic
h
  denotes how to close the connection: 0 means to disable further
  reading, 1 to disable writing and 2 disables both.

  The quick example below is a fragment of a very simple client proces
s.
  After establishing the connection with the server it forks.  Then
  child sends the keyboard input to the server until EOF is received a
nd
  the parent receives answers from the server.

       /*
        *      Sample client fragment,
        *      variables declarations and error handling are omitted
        */
               s=connect(...);

               if( fork() ){   /*      The child, it copies its stdin 
to
                                               the socket             
 */
                       while( gets(buffer) >0)
                               write(s,buf,strlen(buffer));

                       close(s);
                       exit(0);
                       }

               else {          /* The parent, it receives answers  */

                       while( (l=read(s,buffer,sizeof(buffer)){
                               do_something(l,buffer);

                       /* Connection break from the server is assumed 
 */
                       /* ATTENTION: deadlock here                    
 */
                       wait(0); /* Wait for the child to exit         
 */
                       exit(0);
                       }

  What do we expect? The child detects an EOF from its stdin, it close
s
  the socket (assuming connection break) and exits.  The server in its

  turn detects EOF, closes connection and exits.  The parent detects
  EOF, makes the wait() system call and exits.  What do we see instead
?
  The socket instance in the parent process is still opened for writin
g
  and reading, though the parent never writes.  The server never detec
ts
  EOF and waits for more data from the client forever.  The parent nev
er
  sees the connection is closed and hangs forever and the server hangs

  too.  Unexpected deadlock!  ( any deadlock is unexpected though :-)


  You should change the client fragment as follows:

                       if( fork() ) {  /* The child                   
 */
                               while( gets(buffer) }
                                       write(s,buffer,strlen(buffer));


                                       shutdown(s,1); /* Break the con
nection
               for writing, The server will detect EOF now. Note: read
ing from
               the socket is still allowed. The server may send some m
ore data
               after receiving EOF, why not? */
                               exit(0);
                               }

  I hope this rough example explains the troubles you can have with
  client/server syncronization.  Generally you should always remember

  all the instances of the particular socket in all the processes that

  share the socket and close them all at once if you whish to use
  close() or use shutdown() in one process to break the connection.

  2.7.  Please explain the TIME_WAIT state.

  Remember that TCP guarantees all data transmitted will be delivered,

  if at all possible.  When you close a socket, the server goes into a

  TIME_WAIT state, just to be really really sure that all the data has

  gone through.  When a socket is closed, both sides agree by sending

  messages to each other that they will send no more data.  This, it
  seemed to me was good enough, and after the handshaking is done, the

  socket should be closed.  The problem is two-fold.  First, there is 
no
  way to be sure that the last ack was communicated successfully.
  Second, there may be "wandering duplicates" left on the net that mus
t
  be dealt with if they are delivered.

  Andrew Gierth ([email protected]) helped to explain the
  closing sequence in the following usenet posting:

  Assume that a connection is in ESTABLISHED state, and the client is

  about to do an orderly release. The client's sequence no. is Sc, and

  the server's is Ss. The pipe is empty in both directions.

          Client                                                   Ser
ver
          ======                                                   ===
===
          ESTABLISHED                                              EST
ABLISHED
          (client closes)
          ESTABLISHED                                              EST
ABLISHED
                       <CTL=FIN+ACK><SEQ=Sc><ACK=Ss> ------->>
          FIN_WAIT_1
                       <<-------- <CTL=ACK><SEQ=Ss><ACK=Sc+1>
          FIN_WAIT_2                                               CLO
SE_WAIT
                       <<-------- <CTL=FIN+ACK><SEQ=Ss><ACK=Sc+1>  (se
rver closes)
                                                                   LAS
T_ACK
                       <CTL=ACK>,<SEQ=Sc+1><ACK=Ss+1> ------->>
          TIME_WAIT                                                CLO
SED
          (2*msl elapses...)
          CLOSED

  Note: the +1 on the sequence numbers is because the FIN counts as on
e
  byte of data. (The above diagram is equivalent to fig. 13 from RFC
  793).

  Now consider what happens if the last of those packets is dropped in

  the network. The client has done with the connection; it has no more

  data or control info to send, and never will have. But the server do
es
  not know whether the client received all the data correctly; that's

  what the last ACK segment is for. Now the server may or may not care

  whether the client got the data, but that is not an issue for TCP; T
CP
  is a reliable rotocol, and must distinguish between an orderly
  connection close where all data is transferred, and a connection abo
rt
  where data may or may not have been lost.

  So, if that last packet is dropped, the server will retransmit it (i
t
  is, after all, an unacknowledged segment) and will expect to see a
  suitable ACK segment in reply.  If the client went straight to CLOSE
D,
  the only possible response to that retransmit would be a RST, which

  would indicate to the server that data had been lost, when in fact i
t
  had not been.

  (Bear in mind that the server's FIN segment may, additionally, conta
in
  data.)

  DISCLAIMER: This is my interpretation of the RFCs (I have read all t
he
  TCP-related ones I could find), but I have not attempted to examine

  implementation source code or trace actual connections in order to
  verify it. I am satisfied that the logic is correct, though.

  More commentarty from Vic:

  The second issue was addressed by Richard Stevens ([email protected]
,
  author of "Unix Network Programming", see ``1.5 Where can I get sour
ce
  code for the book [book  title]?'').  I have put together quotes fro
m
  some of his postings and email which explain this.  I have brought
  together paragraphs from different postings, and have made as few
  changes as possible.

  From Richard Stevens ([email protected]):

  If the duration of the TIME_WAIT state were just to handle TCP's ful
l-
  duplex close, then the time would be much smaller, and it would be
  some function of the current RTO (retransmission timeout), not the M
SL
  (the packet lifetime).

  A couple of points about the TIME_WAIT state.

  o  The end that sends the first FIN goes into the TIME_WAIT state,
     because that is the end that sends the final ACK.  If the other
     end's FIN is lost, or if the final ACK is lost, having the end th
at
     sends the first FIN maintain state about the connection guarantee
s
     that it has enough information to retransmit the final ACK.

  o  Realize that TCP sequence numbers wrap around after 2**32 bytes
     have been transferred.  Assume a connection between A.1500 (host 
A,
     port 1500) and B.2000.  During the connection one segment is lost

     and retransmitted.  But the segment is not really lost, it is hel
d
     by some intermediate router and then re-injected into the network
.
     (This is called a "wandering duplicate".)  But in the time betwee
n
     the packet being lost & retransmitted, and then reappearing, the

     connection is closed (without any problems) and then another
     connection is established between the same host, same port (that

     is, A.1500 and B.2000; this is called another "incarnation" of th
e
     connection).  But the sequence numbers chosen for the new
     incarnation just happen to overlap with the sequence number of th
e
     wandering duplicate that is about to reappear.  (This is indeed
     possible, given the way sequence numbers are chosen for TCP
     connections.)  Bingo, you are about to deliver the data from the

     wandering duplicate (the previous incarnation of the connection) 
to
     the new incarnation of the connection.  To avoid this, you do not

     allow the same incarnation of the connection to be reestablished

     until the TIME_WAIT state terminates.

     Even the TIME_WAIT state doesn't complete solve the second proble
m,
     given what is called TIME_WAIT assassination.  RFC 1337 has more

     details.

  o  The reason that the duration of the TIME_WAIT state is 2*MSL is
     that the maximum amount of time a packet can wander around a
     network is assumed to be MSL seconds.  The factor of 2 is for the

     round-trip.  The recommended value for MSL is 120 seconds, but
     Berkeley-derived implementations normally use 30 seconds instead.

     This means a TIME_WAIT delay between 1 and 4 minutes.  Solaris 2.
x
     does indeed use the recommended MSL of 120 seconds.

  A wandering duplicate is a packet that appeared to be lost and was
  retransmitted.  But it wasn't really lost ... some router had
  problems, held on to the packet for a while (order of seconds, could

  be a minute if the TTL is large enough) and then re-injects the pack
et
  back into the network.  But by the time it reappears, the applicatio
n
  that sent it originally has already retransmitted the data contained

  in that packet.

  Because of these potential problems with TIME_WAIT assassinations, o
ne
  should not avoid the TIME_WAIT state by setting the SO_LINGER option

  to send an RST instead of the normal TCP connection termination
  (FIN/ACK/FIN/ACK).  The TIME_WAIT state is there for a reason; it's

  your friend and it's there to help you :-)

  I have a long discussion of just this topic in my just-released
  "TCP/IP Illustrated, Volume 3".  The TIME_WAIT state is indeed, one 
of
  the most misunderstood features of TCP.

  I'm currently rewriting "Unix Network Programming" (see ``1.5 Where

  can I get source code for the book [book  title]?''). and will inclu
de
  lots more on this topic, as it is often confusing and misunderstood.


  An additional note from Andrew:

  Closing a socket: if SO_LINGER has not been called on a socket, then

  close() is not supposed to discard data. This is true on SVR4.2 (and
,
  apparently, on all non-SVR4 systems) but apparently not on SVR4; the

  use of either shutdown() or SO_LINGER seems to be required to
  guarantee delivery of all data.

  2.8.  Why does it take so long to detect that the peer died?

  From Andrew Gierth ([email protected]):

  Because by default, no packets are sent on the TCP connection unless

  there is data to send or acknowledge.

  So, if you are simply waiting for data from the peer, there is no wa
y
  to tell if the peer has silently gone away, or just isn't ready to
  send any more data yet. This can be a problem (especially if the pee
r
  is a PC, and the user just hits the Big Switch...).

  One solution is to use the SO_KEEPALIVE option. This option enables

  periodic probing of the connection to ensure that the peer is still

  present.  BE WARNED: the default timeout for this option is AT LEAST
 2
  HOURS.  This timeout can often be altered (in a system-dependent
  fashion) but not normally on a per-connection basis (AFAIK).

  RFC1122 specifies that this timeout (if it exists) must be
  configurable.  On the majority of Unix variants, this configuration

  may only be done globally, affecting all TCP connections which have

  keepalive enabled. The method of changing the value, moreover, is
  often difficult and/or poorly documented, and in any case is differe
nt
  for just about every version in existence.

  If you must change the value, look for something resembling
  tcp_keepidle in your kernel configuration or network options
  configuration.

  If you're sending to the peer, though, you have some better
  guarantees; since sending data implies receiving ACKs from the peer,

  then you will know after the retransmit timeout whether the peer is

  still alive. But the retransmit timeout is designed to allow for
  various contingencies, with the intention that TCP connections are n
ot
  dropped simply as a result of minor network upsets. So you should
  still expect a delay of several minutes before getting notification 
of
  the failure.

  The approach taken by most application protocols currently in use on

  the Internet (e.g. FTP, SMTP etc.) is to implement read timeouts on

  the server end; the server simply gives up on the client if no
  requests are received in a given time period (often of the order of 
15
  minutes). Protocols where the connection is maintained even if idle

  for long periods have two choices:

  1. use SO_KEEPALIVE

  2. use a higher-level keepalive mechanism (such as sending a null
     request to the server every so often).

  2.9.  What are the pros/cons of select(), non-blocking I/O and SIGIO
?

  Using non-blocking I/O means that you have to poll sockets to see if

  there is data to be read from them.  Polling should usually be avoid
ed
  since it uses more CPU time than other techniques.

  Using SIGIO allows your application to do what it does and have the

  operating system tell it (with a signal) that there is data waiting

  for it on a socket.  The only drawback to this soltion is that it ca
n
  be confusing, and if you are dealing with multiple sockets you will

  have to do a select() anyway to find out which one(s) is ready to be

  read.

  Using select() is great if your application has to accept data from

  more than one socket at a time since it will block until any one of 
a
  number of sockets is ready with data.  One other advantage to select
()
  is that you can set a time-out value after which control will be
  returned to you whether any of the sockets have data for you or not.


  2.10.  Why do I get EPROTO from read()?

  From Steve Rago ([email protected]):

  EPROTO means that the protocol encountered an unrecoverable error fo
r
  that endpoint.  EPROTO is one of those catch-all error codes used by

  STREAMS-based drivers when a better code isn't available.

  And an addition note from Andrew ([email protected]):

  Not quite to do with EPROTO from read(), but I found out once that o
n
  some STREAMS-based implementations, EPROTO could be returned by
  accept() if the incoming connection was reset before the accept
  completes.

  On some other implementations, accept seemed to be capable of blocki
ng
  if this occured. This is important, since if select() said the
  listening socket was readable, then you would normally expect not to

  block in the accept() call. The fix is, of course, to set nonblockin
g
  mode on the listening socket if you are going to use select() on it.


  2.11.  How can I force a socket to send the data in its buffer?

  From Richard Stevens ([email protected]):

  You can't force it.  Period.  TCP makes up its own mind as to when i
t
  can send data.  Now, normally when you call write() on a TCP socket,

  TCP will indeed send a segment, but there's no guarantee and no way 
to
  force this.  There are lots of reasons why TCP will not send a
  segment: a closed window and the Nagle algorithm are two things to
  come immediately to mind.

  (Snipped suggestion from Andrew Gierth to use TCP_NODELAY)

  Setting this only disables one of the many tests, the Nagle algorith
m.
  But if the original poster's problem is this, then setting this sock
et
  option will help.

  A quick glance at tcp_output() shows around 11 tests TCP has to make

  as to whether to send a segment or not.

  Now from Dr. Charles E. Campbell Jr.  ([email protected]):

  As you've surmised, I've never had any problem with disabling Nagle'
s
  algorithm.  Its basically a buffering method; there's a fixed overhe
ad
  for all packets, no matter how small.  Hence, Nagle's algorithm
  collects small packets together (no more than .2sec delay) and there
by
  reduces the amount of overhead bytes being transferred.  This approa
ch
  works well for rcp, for example: the .2 second delay isn't humanly
  noticeable, and multiple users have their small packets more
  efficiently transferred.  Helps in university settings where most
  folks using the network are using standard tools such as rcp and ftp
,
  and programs such as telnet may use it, too.

  However, Nagle's algorithm is pure havoc for real-time control and n
ot
  much better for keystroke interactive applications (control-C,
  anyone?).  It has seemed to me that the types of new programs using

  sockets that people write usually do have problems with small packet

  delays.  One way to bypass Nagle's algorithm selectively is to use
  "out-of-band" messaging, but that is limited in its content and has

  other effects (such as a loss of sequentiality) (by the way, out-of-

  band is often used for that ctrl-C, too).

  More from Vic:

  So to sum it all up, if you are having trouble and need to flush the

  socket, setting the TCP_NODELAY option will usually solve the proble
m.
  If it doesn't, you will have to use out-of-band messaging, but
  according to Andrew, "out-of-band data has its own problems, and I
  don't think it works well as a solution to buffering delays (haven't

  tried it though).  It is not 'expedited data' in the sense that exis
ts
  in some other protocols; it is transmitted in-stream, but with a
  pointer to indicate where it is."

  I asked Andrew something to the effect of "What promises does TCP ma
ke
  about when it will get around to writing data to the network?"  I
  thought his reply should be put under this question:
  Not many promises, but some.

  I'll try and quote chapter and verse on this:

  References:

       RFC 1122, "Requirements for Internet Hosts" (also STD 3)
       RFC  793, "Transmission Control Protocol"   (also STD 7)

  1. The socket interface does not provide access to the TCP PUSH flag
.

  2. RFC1122 says (4.2.2.2):

     A TCP MAY implement PUSH flags on SEND calls.  If PUSH flags are

     not implemented, then the sending TCP: (1) must not buffer data
     indefinitely, and (2) MUST set the PSH bit in the last buffered
     segment (i.e., when there is no more queued data to be sent).

  3. RFC793 says (2.8):

     When a receiving TCP sees the PUSH flag, it must not wait for mor
e
     data from the sending TCP before passing the data to the receivin
g
     process.

     [RFC1122 supports this statement.]

  4. Therefore, data passed to a write() call must be delivered to the

     peer within a finite time, unless prevented by protocol
     considerations.

  5. There are (according to a post from Stevens quoted in the FAQ
     [earlier in this answer - Vic]) about 11 tests made which could
     delay sending the data. But as I see it, there are only 2 that ar
e
     significant, since things like retransmit backoff are a) not unde
r
     the programmers control and b) must either resolve within a finit
e
     time or drop the connection.

  The first of the interesting cases is "window closed"  (ie. there is

  no buffer space at the receiver; this can delay data indefinitely, b
ut
  only if the receiving process is not actually reading the data that 
is
  available)

  Vic asks:

  OK, it makes sense that if the client isn't reading, the data isn't

  going to make it across the connection.  I take it this causes the
  sender to block after the recieve queue is filled?

  The sender blocks when the socket send buffer is full, so buffers wi
ll
  be full at both ends.

  While the window is closed, the sending TCP sends window probe
  packets. This ensures that when the window finally does open again,

  the sending TCP detects the fact. [RFC1122, ss 4.2.2.17]

  The second interesting case is "Nagle algorithm" (small segments, e.
g.
  keystrokes, are delayed to form larger segments if ACKs are expected

  from the peer; this is what is disabled with TCP_NODELAY)

  Vic Asks:

  Does this mean that my tcpclient sample should set TCP_NODELAY to
  ensure that the end-of-line code is indeed put out onto the network

  when sent?

  No. tcpclient.c is doing the right thing as it stands; trying to wri
te
  as much data as possible in as few calls to write() as is feasible.

  Since the amount of data is likely to be small relative to the socke
t
  send buffer, then it is likely (since the connection is idle at that

  point) that the entire request will require only one call to write()
,
  and that the TCP layer will immediately dispatch the request as a
  single segment (with the PSH flag, see point 2.2 above).

  The Nagle algorithm only has an effect when a second write() call is

  made while data is still unacknowledged. In the normal case, this da
ta
  will be left buffered until either: a) there is no unacknowledged
  data; or b) enough data is available to dispatch a full-sized segmen
t.
  The delay cannot be indefinite, since condition (a) must become true

  within the retransmit timeout or the connection dies.

  Since this delay has negative consequences for certain applications,

  generally those where a stream of small requests are being sent
  without response, e.g. mouse movements, the standards specify that a
n
  option must exist to disable it. [RFC1122, ss 4.2.3.4]

  Additional note: RFC1122 also says:

     [DISCUSSION]:
        When the PUSH flag is not implemented on SEND calls, i.e., whe
n
        the application/TCP interface uses a pure streaming model,
        responsibility for aggregating any tiny data fragments to form

        reasonable sized segments is partially borne by the applicatio
n
        layer.

  So programs should avoid calls to write() with small data lengths
  (small relative to the MSS, that is); it's better to build up a
  request in a buffer and then do one call to sock_write() or
  equivalent.

  The other possible sources of delay in the TCP are not really
  controllable by the program, but they can only delay the data
  temporarily.

  Vic asks:

  By temporarily, you mean that the data will go as soon as it can, an
d
  I won't get stuck in a position where one side is waiting on a
  response, and the other side hasn't recieved the request?  (Or at
  least I won't get  stuck forever)

  You can only deadlock if you somehow manage to fill up all the buffe
rs
  in both directions... not easy.

  If it is possible to do this, (can't think of a good example though)
,
  the solution is to use nonblocking mode, especially for writes. Then

  you can buffer excess data in the program as necessary.

  2.12.  Where can a get a library for programming sockets?

  There is the Simple Sockets Library by Charles E. Campbell, Jr. PhD.

  and Terry McRoberts.  The file is called ssl.tar.gz, and you can
  download it from this faq's home page.  For c++ there is the Socket+
+
  library which is on ftp://ftp.virginia.edu/pub/socket++-1.10.tar.gz.

  There is also C++ Wrappers.  The file is called
  ftp://ftp.huji.ac.il/pub/languages/C++/C++_wrappers.tar.gz.  Thanks 
to
  Bill McKinnon for tracking it down for me!  From
  http://www.cs.wustl.edu/~schmidt you should be able to find the ACE

  toolkit.  PING Software Group has some libraries that include a
  sockets interface among other things.  You can find them at
  http://love.geology.yale.edu/~markl/ping.

  I don't have any experience with any of these libraries, so I can't

  recomend one over the other.

  2.13.  How come select says there is data, but read returns zero?

  The data that causes select to return is the EOF because the other
  side has closed the connection.  This causes read to return zero.  F
or
  more information see ``2.1 How can I tell when a socket is closed on

  the other end?''

  2.14.  Whats the difference between select() and poll()?

  From Richard Stevens ([email protected]):

  The basic difference is that select()'s fd_set is a bit mask and
  therefore has some fixed size.  It would be possible for the kernel 
to
  not limit this size when the kernel is compiled, allowing the
  application to define FD_SETSIZE to whatever it wants (as the commen
ts
  in the system header imply today) but it takes more work.  4.4BSD's

  kernel and the Solaris library function both have this limit.  But I

  see that BSD/OS 2.1 has now been coded to avoid this limit, so it's

  doable, just a small matter of programming. :-)  Someone should file
 a
  Solaris bug report on this, and see if it ever gets fixed.

  With poll(), however, the user must allocate an array of pollfd
  structures, and pass the number of entries in this array, so there's

  no fundamental limit.  As Casper notes, fewer systems have poll() th
an
  select, so the latter is more portable.  Also, with original
  implementations (SVR3) you could not set the descriptor to -1 to tel
l
  the kernel to ignore an entry in the pollfd structure, which made it

  hard to remove entries from the array; SVR4 gets around this.
  Personally, I always use select() and rarely poll(), because I port 
my
  code to BSD environments too.  Someone could write an implementation

  of poll() that uses select(), for these environments, but I've never

  seen one. Both select() and poll() are being standardized by POSIX
  1003.1g.

  2.15.  How do I send [this] over a socket?

  Anything other than single bytes of data will probably get mangled
  unless you take care.  For integer values you can use htons() and
  friends, and strings are really just a bunch of single bytes, so tho
se
  should be OK.  Be careful not to send a pointer to a string though,

  since the pointer will be meaningless on another machine.  If you ne
ed
  to send a struct, you should write sendthisstruct() and
  readthisstruct() functions for it that do all the work of taking the

  structure apart on one side, and putting it back together on the
  other.  If you need to send floats, you may have a lot of work ahead

  of you.  You should read RFC 1014 which is about portable ways of
  getting data from one machine to another (thanks to Andrew Gabriel f
or
  pointing this out).

  2.16.  How do I use TCP_NODELAY?

  First off, be sure you really want to use it in the first place.  It

  will disable the Nagle algorithm (see ``2.11 How can I force a socke
t
  to send the data in its buffer?''), which will cause network traffic

  to increase, with smaller than needed packets wasting bandwidth.
  Also, from what I have been able to tell, the speed increase is very

  small, so you should probably do it without TCP_NODELAY first, and
  only turn it on if there is a problem.

  Here is a code example, with a warning about using it from Andrew
  Gierth:

         int flag = 1;
         int result = setsockopt(sock,            /* socket affected *
/
                                 IPPROTO_TCP,     /* set option at TCP
 level */
                                 TCP_NODELAY,     /* name of option */

                                 (char *) &flag,  /* the cast is histo
rical
                                                         cruft */
                                 sizeof(int));    /* length of option 
value */
         if (result < 0)
... handle the error ...

TCP_NODELAY is for a specific purpose; to disable the Nagle bufferin
g
algorithm. It should only be set for applications that send frequent

small bursts of information without getting an immediate response,
where timely delivery of data is required (the canonical example is

mouse movements).

2.17. What exactly does the Nagle algorithm do?

It groups together as much data as it can between ACK's from the oth
er
end of the connection. I found this really confusing until Andrew
Gierth ([email protected]) drew the following diagram, an
d
explained:

This diagram is not intended to be complete, just to illustrate the

point better...

Case 1: client writes 1 byte per write() call. The program on host B

is tcpserver.c from the FAQ examples.

CLIENT SERVER
APP TCP TCP APP
[connection setup omitted]

"h" --------->          [1 byte]
                      ------------------>
                                             -----------> "h"
                                     [ack delayed]
   "e" ---------> [Nagle alg.              .
                   now in effect]          .
   "l" ---------> [ditto]                  .
   "l" ---------> [ditto]                  .
   "o" ---------> [ditto]                  .
   "\n"---------> [ditto]                  .
                                           .
                                           .
                         [ack 1 byte]
                      <------------------
[send queued
data]
[5 bytes]
------------------>
                                            ------------> "ello\n"
                                            <------------ "HELLO\n"
[6 bytes, ack 5 bytes]
<------------------
"HELLO\n" <----
[ack delayed]
.
.
. [ack 6 bytes]
------------------>

  Total segments: 5. (If TCP_NODELAY was set, could have been up to 10
.)
  Time for response: 2*RTT, plus ack delay.

  Case 2: client writes all data with one write() call.

             CLIENT                                  SERVER
       APP             TCP                     TCP             APP
                       [connection setup omitted]

        "hello\n" --->          [6 bytes]
                           ------------------>
                                                 ------------> "hello\
n"
                                                 <------------ "HELLO\
n"
[6 bytes, ack 6 bytes]
<------------------
"HELLO\n" <----
[ack delayed]
.
.
. [ack 6 bytes]
------------------>

  Total segments: 3.

  Time for response = RTT (therefore minimum possible).

  Hope this makes things a bit clearer...

  Note that in case 2, you don't want the implementation to gratuitous
ly
  delay sending the data, since that would add straight onto the
  response time.

  2.18.  What is the difference between read() and recv()?

  From Andrew Gierth ([email protected]):

  read() is equivalent to recv() with a flags parameter of 0.  Other
  values for the flags parameter change the behaviour of recv().
  Similarly, write() is equivalent to send() with flags == 0.

  It is unlikely that send()/recv() would be dropped; perhaps someone

  with a copy of the POSIX drafts for socket calls can check...

  Portability note: non-unix systems may not allow read()/write() on
  sockets, but recv()/send() are usually ok. This is true on Windows a
nd
  OS/2, for example.

  2.19.  I see that send()/write() can generate SIGPIPE. Is there any

  advantage to handling the signal, rather than just ignoring it and
  checking for the EPIPE error? Are there any useful parameters passed

  to the signal catching function?

  From Andrew Gierth ([email protected]):

  In general, the only parameter passed to a signal handler is the
  signal number that caused it to be invoked.  Some systems have
  optional additional parameters, but they are no use to you in this
  case.

  My advice is to just ignore SIGPIPE as you suggest. That's what I do

  in just about all of my socket code; errno values are easier to hand
le
  than signals (in fact, the first revision of the FAQ failed to menti
on
  SIGPIPE in that context; I'd got so used to ignoring it...)

  There is one situation where you should not ignore SIGPIPE; if you a
re
  going to exec() another program with stdout redirected to a socket. 
In
  this case it is probably wise to set SIGPIPE to SIG_DFL before doing

  the exec().

  2.20.  After the chroot(), calls to socket() are failing.  Why?

  From Andrew Gierth ([email protected]):

  On systems where sockets are implemented on top of Streams (e.g. all

  SysV-based systems, presumably including Solaris), the socket()
  function will actually be opening certain special files in /dev. You

  will need to create a /dev directory under your fake root and popula
te
  it with the required device nodes (only).

  Your system documentation may or may not specify exactly which devic
e
  nodes are required; I can't help you there (sorry).  (Editors note:

  Adrian Hall ([email protected]) suggested checking the man

  page for ftpd, which should list the files you need to copy and
  devices you need to create in the chroot'd environment.)

  A less-obvious issue with chroot() is if you call syslog(), as many

  daemons do; syslog() opens (depending on the system) either a UDP
  socket, a FIFO or a Unix-domain socket. So if you use it after a
  chroot() call, make sure that you call openlog() *before* the chroot
.

  2.21.  Why do I keep getting EINTR from the socket calls?

  This isn't really so much an error as an exit condition.  It means
  that the call was interrupted by a signal.  Any call that might bloc
k
  should be wrapped in a loop that checkes for EINTR, as is done in th
e
  example code (See ``6. Sample Source Code'').

  2.22.  When will my application receive SIGPIPE?

  From Richard Stevens ([email protected]):

  Very simple: with TCP you get SIGPIPE if your end of the connection

  has received an RST from the other end.  What this also means is tha
t
  if you were using select instead of write, the select would have
  indicated the socket as being readable, since the RST is there for y
ou
  to read (read will return an error with errno set to ECONNRESET).

  Basically an RST is TCP's response to some packet that it doesn't
  expect and has no other way of dealing with.  A common case is when

  the peer closes the connection (sending you a FIN) but you ignore it

  because you're writing and not reading.  (You should be using select
.)
  So you write to a connection that has been closed by the other end a
nd
  the oether end's TCP responds with an RST.

  2.23.  What are socket exceptions?  What is out-of-band data?

  Unlike exceptions in C++, socket exceptions do not indicate that an

  error has occured.  Socket exceptions usually refer to the
  notification that out-of-band data has arrived.  Out-of-band data
  (called "urgent data" in TCP) looks to the application like a separa
te
  stream of data from the main data stream.  This can be useful for
  separating two different kinds of data.  Note that just because it i
s
  called "urgent data" does not mean that it will be delivered any
  faster, or with higher priorety than data in the in-band data stream
.
  Also beware that unlike the main data stream, the out-of-bound data

  may be lost if your application can't keep up with it.

  2.24.  running on?  How can I find the full hostname (FQDN) of the
  system I'm

  From Richard Stevens ([email protected]):

  Some systems set the hostname to the FQDN and others set it to just

  the unqualified host name.  I know the current BIND FAQ recommends t
he
  FQDN, but most Solaris systems, for example, tend to use only the
  unqualified host name.

  Regardless, the way around this is to first get the host's name
  (perhaps an FQDN, perhaps unaualified).  Most systems support the
  Posix way to do this using uname(), but older BSD systems only provi
de
  gethostname().  Call gethostbyname() to find your IP address.  Then

  take the IP address and call gethostbyaddr().  The h_name member of

  the hostent{} should then be your FQDN.

  3.  Writing Client Applications (TCP/SOCK_STREAM)

  3.1.  How do I convert a string into an internet address?

  If you are reading a host's address from the command line, you may n
ot
  know if you have an aaa.bbb.ccc.ddd style address, or a
  host.domain.com style address.  What I do with these, is first try t
o
  use it as a aaa.bbb.ccc.ddd type address, and if that fails, then do
 a
  name lookup on it.  Here is an example:

       /* Converts ascii text to in_addr struct.  NULL is returned if 
the
          address can not be found. */
       struct in_addr *atoaddr(char *address) {
         struct hostent *host;
         static struct in_addr saddr;

         /* First try it as aaa.bbb.ccc.ddd. */
         saddr.s_addr = inet_addr(address);
         if (saddr.s_addr != -1) {
           return &saddr;
         }
         host = gethostbyname(address);
         if (host != NULL) {
           return (struct in_addr *) *host->h_addr_list;
         }
         return NULL;
       }

  3.2.  How can my client work through a firewall/proxy server?

  If you are running through separate proxies for each service, you
  shouldn't need to do anything.  If you are working through sockd, yo
u
  will need to "socksify" your application.  Details for doing this ca
n
  be found in the package itself, which is available at:

       ftp://ftp.net.com/socks.cstc/socks.cstc.4.2.tar.gz

  you can get the socks faq at:

       ftp://coast.cs.purdue.edu/pub/tools/unix/socks/FAQ

  3.3.  Why does connect() succeed even before my server did an
  accept()?

  From Andrew Gierth ([email protected]):

  Once you have done a listen() call on your socket, the kernel is
  primed to accept connections on it. The usual UNIX implementation of

  this works by immediately completing the SYN handshake for any
  incoming valid SYN segments (connection attempts), creating the sock
et
  for the new connection, and keeping this new socket on an internal
  queue ready for the accept() call. So the socket is fully open befor
e
  the accept is done.

  The other factor in this is the 'backlog' parameter for listen(); th
at
  defines how many of these completed connections can be queued at one

  time.  If the specified number is exceeded, then new incoming connec
ts
  are simply ignored (which causes them to be retried).

  3.4.  Why do I sometimes lose a server's address when using more tha
n
  one server?

  From Andrew Gierth ([email protected]):

  Take a careful look at struct hostent. Notice that almost everything

  in it is a pointer? All these pointers will refer to statically
  allocated data.

  For example, if you do:

           struct hostent *host = gethostbyname(hostname);

  then (as you should know) a subsequent call to gethostbyname() will

  overwrite the structure pointed to by 'host'.

  But if you do:

           struct hostent myhost;
           struct hostent *hostptr = gethostbyname(hostname);
           if (hostptr) myhost = *host;

  to make a copy of the hostent before it gets overwritten, then it
  still gets clobbered by a subsequent call to gethostbyname(), since

  although myhost won't get overwritten, all the data it is pointing t
o
  will be.

  You can get round this by doing a proper 'deep copy' of the hostent

  structure, but this is tedious. My recommendation would be to extrac
t
  the needed fields of the hostent and store them in your own way.

  Robin Paterson ([email protected]) has added:

  It might be nice if you mention MT safe libraries provide
  complimentary functions for multithreaded programming.  On the solar
is
  machine I'm typing at, we have gethostbyname and gethostbyname_r (_r

  for reentrant).  The main difference is, you provide the storage for

  the hostent struct so you always have a local copy and not just a
  pointer to the static copy.

  3.5.  How can I set the timeout for the connect() system call?

  From Richard Stevens ([email protected]):

  Normally you cannot change this.  Solaris does let you do this, on a

  per-kernel basis with the ndd tcp_ip_abort_cinterval parameter.

  The easiest way to shorten the connect time is with an alarm() aroun
d
  the call to connect().  A harder way is to use select(), after setti
ng
  the socket nonblocking.  Also notice that you can only shorten the
  connect time, there's normally no way to lengthen it.

  From Andrew Gierth ([email protected]):

  First, create the socket and put it into non-blocking mode, then cal
l
  connect(). There are three possibilities:

  o  connect succeeds: the connection has been successfully made (this

     usually only happens when connecting to the same machine)

  o  connect fails: obvious

  o  connect returns -1/EINPROGRESS. The connection attempt has begun,

     but not yet completed.

  If the connection succeeds:

  o  the socket will select() as writable (and will also select as
     readable if data arrives)

  If the connection fails:

  o  the socket will select as readable *and* writable, but either a
     read or write will return the error code from the connection
     attempt. Also, you can use getsockopt(SO_ERROR) to get the error

     status - but be careful; some systems return the error code in th
e
     result parameter of getsockopt, but others (incorrectly) cause th
e
     getsockopt call *itself* to fail with the stored value as the
     error.

  3.6.  system choose one for me on the connect() call?  Should I bind
()
  a port number in my client program, or let the

  From Andrew Gierth ([email protected]):

  ** Let the system choose your client's port number **

  The exception to this, is if the server has been written to be picky

  about what client ports it will allow connections from. Rlogind and

  rshd are the classic examples. This is usually part of a Unix-specif
ic
  (and rather weak) authentication scheme; the intent is that the serv
er
  allows connections only from processes with root privilege. (The
  weakness in the scheme is that many O/Ss (e.g. MS-DOS) allow anyone 
to
  bind any port.)

  The rresvport() routine exists to help out clients that are using th
is
  scheme. It basically does the equivalent of socket() + bind(),
  choosing a port number in the range 512..1023.

  If the server is not fussy about the client's port number, then don'
t
  try and assign it yourself in the client, just let connect() pick it

  for you.

  If, in a client, you use the naive scheme of starting at a fixed por
t
  number and calling bind() on consecutive values until it works, then

  you buy yourself a whole lot of trouble:

  The problem is if the server end of your connection does an active
  close.  (E.G. client sends 'QUIT' command to server, server responds

  by closing the connection). That leaves the client end of the
  connection in CLOSED state, and the server end in TIME_WAIT state. S
o
  after the client exits, there is no trace of the connection on the
  client end.

  Now run the client again. It will pick the same port number, since a
s
  far as it can see, it's free. But as soon as it calls connect(), the

  server finds that you are trying to duplicate an existing connection

  (although one in TIME_WAIT). It is perfectly entitled to refuse to d
o
  this, so you get, I suspect, ECONNREFUSED from connect(). (Some
  systems may sometimes allow the connection anyway, but you can't rel
y
  on it.)

  This problem is especially dangerous because it doesn't show up unle
ss
  the client and server are on different machines. (If they are the sa
me
  machine, then the client won't pick the same port number as before).

  So you can get bitten well into the development cycle (if you do wha
t
  I suspect most people do, and test client & server on the same box
  initially).

  Even if your protocol has the client closing first, there are still

  ways to produce this problem (e.g. kill the server).

  3.7.  Why do I get "connection refused" when the server isn't runnin
g?

  The connect() call will only block while it is waiting to establish 
a
  connection.  When there is no server waiting at the other end, it ge
ts
  notified that the connection can not be established, and gives up wi
th
  the error message you see.  This is a good thing, since if it were n
ot
  the case clients might wait for ever for a service which just doesn'
t
  exist.  Users would think that they were only waiting for the
  connection to be established, and then after a while give up,
  muttering something about crummy software under their breath.

  3.8.  over the socket ? Is there a way to have a dynamic buffer ?
  What does one do when one does not know how much information is com-

  ming

  This question asked by Niranjan Perera ([email protected]).

  When the size of the incoming data is unknown, you can either make t
he
  size of the buffer as big as the largest possible (or likely) buffer
,
  or you can re-size the buffer on the fly during your read.  When you

  malloc() a large buffer, most (if not all) varients of unix will onl
y
  allocate address space, but not physical pages of ram.  As more and

  more of the buffer is used, the kernel allocates physical memory.
  This means that malloc'ing a large buffer will not waste resources
  unless that memory is used, and so it is perfectly acceptable to ask

  for a meg of ram when you expect only a few K.

  On the other hand, a more elegant solution that does not depend on t
he
  inner workings of the kernel is to use realloc() to expand the buffe
r
  as required in say 4K chunks (since 4K is the size of a page of ram 
on
  most systems).  I may add something like this to sockhelp.c in the
  example code one day.

  4.  Writing Server Applications (TCP/SOCK_STREAM)

  4.1.  How come I get "address already in use" from bind()?

  You get this when the address is already in use.  (Oh, you figured
  that much out?)  The most common reason for this is that you have
  stopped your server, and then re-started it right away.  The sockets

  that were used by the first incarnation of the server are still
  active.  This is further explained in ``2.7 Please explain the
  TIME_WAIT state.'', and ``2.5 How do I properly close a socket?''.

  4.2.  Why don't my sockets close?

  When you issue the close() system call, you are closing your interfa
ce
  to the socket, not the socket itself.  It is up to the kernel to clo
se
  the socket.  Sometimes, for really technical reasons, the socket is

  kep

[关闭][返回]