|
|
This section describes, in the context of the client/server model, the socket system calls needed to create and connect a pair of sockets and transmit data.
A socket created with the socket
call is identified only by its address family and type.
It has no name.
Without a name, processes cannot reference it
and no communication can take place.
Communication processes are bound by an association.
In the UNIX domain, an association is composed of
local and foreign path names (pathnames created by a foreign process).
In the Internet domain, an association
consists of a local address and port number, and a foreign
address and port number.
The
bind(SSC)
system call allows a process to specify the local
half of this association by binding an address to
the local end of a socket.
The call takes the form:
bind(s, name, namelen);
Arguments to bind include the socket, a pointer to the address (name), and the length of the address (namelen). Thus bound, a process is able to rendezvous with an unrelated process. The operation is asymmetric, with one process taking the role of server and the other of client.
Server sockets listen passively for incoming connection requests
rather than actively initiating them.
To create a server socket, call
listen(SSC)
after the socket is bound.
listen(s,backlog);
The listen call identifies the socket that receives the connections and marks it as accepting connections. The maximum queue length (backlog) that listen can specify is five.
A call to listen does not complete the connection;
it only indicates a willingness on the part of the server
process to listen for incoming connection requests.
Applications must call
accept(SSC)
to establish an actual connection.
The accept call takes takes the form:
accept(s, addr, addrlen)
The addr and addrlen arguments return the address of the connected client process, and accept automatically creates a new socket descriptor. Assuming the server is concurrent, the process immediately forks and the child process handles the connection while the parent continues to listen for more connection requests.
Client sockets actively initiate calls, rather than listening passively for incoming connection requests. Active sockets use the connect(SSC) function to establish connections. To create a socket to rendezvous with a server, use the socket call as before. With streams sockets, it is not necessary to bind an address to the client (see table below). This is because with a connection-oriented protocol the server's address must be known, but the client's address is unimportant because no other process will try to access it. With connectionless sockets, however, each datagram must contain the destination address of the client and an address bound to it with the bind system call.
A client process issues the connect
call in an attempt to establish a connection
with a listening server process.
A connection is a mechanism that avoids the need to
transmit the identity of the sending socket
each time data is sent.
The connect call provides for
the exchange of the identities of each endpoint just once,
prior to the transmission of data.
Successful completion of
connect results in a connection between
two sockets.
connect(s, name, namelen)
connect does not return until a connection is established. s is the socket descriptor of the client process. name and namelen are pointers to the address family and size of the other socket.
Establishing a connection
Client | Server | |
---|---|---|
socket() | socket() | |
bind() | ||
listen() | ||
connect() | accept() |
Once a pair of sockets is connected,
data can flow from one to the other.
Data can be sent and received with any of several system calls.
The
read(S)
and
write(C)
functions may be used to do this, just as they are for normal files.
read(fildes, buf, nbyte)
write(fildes, buf, nbyte)
fildes refers to the socket descriptor returned by the socket call in the client, and by accept in the server. The write system call attempts to write nbyte bytes from the buffer pointed to by buf to the socket associated with fildes.
The
send(SSC)
and
recv(SSC)
calls are almost identical to read and
write, except that they provide a flags argument.
send(s, msg, len, flags)
recv(s, msg, len, flags)
The flags argument may be specified as non-zero if the MSG_PEEK constant is required.
The MSG_PEEK flag lets the caller look at the data without discarding it as read. When specified in a recv call, any data present is returned to the user but treated as though still unread. The next read or recv call applied to the socket will return the data previously previewed.
The
close(S)
system call is used to discard the end of a socket connection
when it is no longer needed. If one end of a socket is
closed and the other tries to write to it,
the write will return an error. s is the socket
descriptor being closed in:
close(s)
If the socket is a stream socket, the system will continue
to attempt to transfer data. The
shutdown(SSC)
call causes all or part of a full-duplex connection to be
terminated:
shutdown(s, how)
If argument how is 0, further receives are disabled. When how is 1, further sends are disallowed, while 2 disallows additional sends and receives.