Code samples (Internet domain)
Examples of client and server socket programs
make up the rest of this section.
These programs illustrate how to use
the sockets interface to establish a connection and transmit
data between hosts using TCP.
Server (Internet domain)
The following code creates a
server that waits for client connection requests.
The manual page for each routine defines the necessary
#include files when calling that routine.
Sample server (part 1 of 3)
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #include <stdio.h>
5 #include <netdb.h>
line 1-
System pseudo-types.
line 2-
Definitions related to sockets: types, address families,
options; and structures used by the kernel to store
most addresses.
line 3-
Constants and structures defined by the Internet system, and
definitions of bits in Internet address integers.
line 4-
Standard I/O definitions.
line 5-
Structures returned by network database library. These include,
for example, hostent and netent, which are
returned by gethostbyname and getnetbyname respectively.
See the SCO TCP/IP Programmer's Reference for a full
listing of the sockets library functions.
Sample server (part 2 of 3)
6 #define PORTNUM 601
7 main(argc, argv)
8 int argc;
9 char *argv[];
10 {
11 int s, ns, pid;
12 struct sockaddr_in sin;
13 char buf[80];
14 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
15 perror("tomd: socket");
16 exit(1);
17 }
18 bzero(&sin, sizeof(sin));
19 sin.sin_family = AF_INET;
20 sin.sin_port = htons(PORTNUM);
21 sin.sin_addr.s_addr = htonl(INADDR_ANY);
22 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) {
23 perror("tomd: bind");
24 exit(1);
25 }
26 if (listen(s, 5) == -1) {
27 perror("tomd: listen");
28 exit(1);
29 }
30 while(1)
31 {
32 if ((ns = accept(s, 0, 0)) == -1) {
33 perror("tomd: accept");
34 exit(1);
35 }
36 if ((pid = fork()) == -1) {
37 perror("tomd: fork");
38 exit(1);
39 }
line 6-
This is the port number the server will use. See /etc/services
for a listing of port numbers of common network services.
line 11-
Declare integers: s is the socket descriptor.
ns is the socket descriptor for the connection to the client.
pid is the process ID for the fork.
line 12-
The sockaddr structure for sin is declared.
This allocates space for the Internet address and port number.
line 13-
This is a buffer for data received from the client.
lines 14-16-
Line 14 creates a socket, and establishes an endpoint for
communication.
It is a stream socket in the Internet address family using TCP.
A socket created with the socket system call is identified only
by its address family. As yet it has no name. Other processes
cannot reference it and no communication can take place.
line 18-
This line clears the address space, that is, initializes
sin
to all zeros. See
bstring(S).
line 19-
This line assigns the Internet address family, AF_INET.
line 20-
This line moves the port number, defined in line 6, into the
sin structure.
If this server were advertising a well-known service like telnet,
the port number could be obtained with a call to
getservent(SLIB)
(see lines 6 and 26 in the later client example
for a similar functionality).
line 21-
This line assigns the Internet host address. In this case, the
server will receive data addressed to any of its configured
network interfaces.
lines 22-24-
Communication processes are bound by an association.
An association consists of a local address and port number,
and a foreign address and port number.
bind allows a process to specify the local half of an
association. Here the port number is associated with
the socket channel number.
lines 26-28-
The server waits for a client to attempt to connect.
The listen call identifies a socket as a server
and marks it as accepting connections.
The maximum queue length listen can specify is five.
This means it allows a backlog of five clients
attempting to connect before turning them back.
lines 32-34-
accept automatically creates a new socket
descriptor with the same properties as s.
The second and third arguments to accept
can be used to return the address and address length of
the connected client process.
Setting them to zero causes the server to not retain the
address information of the client, (see
accept(SSC)).
line 36-39-
The call to
fork(S)
creates a child process that is an exact copy of the
calling process.
Sample server (part 3 of 3)
41 if (pid == 0) {
42 while(1) {
43 if ((pid = read(ns, buf, sizeof(buf))) == -1) {
44 perror("tomd: read");
45 exit(1);
46 }
47 if (pid < sizeof(buf)) break;
48 printf("Data from client: %s", buf);
49 }
50 printf("\nThe daemon child is dead\n");
51 close(ns);
52 exit(0);
53 }
54 close(ns);
55 }
56 }
lines 40-41-
The socket is passed on to the child so that the parent
can continue to listen for connection requests from
other clients.
line 42-47-
The server reads the data sent by client.
If the data received is less than
the buffer size (see line 13 above), the loop breaks and the child dies.
line 50-51-
The child closes and exits the connection to the client.
If one end of a socket is closed and the other
tries to write to it, the write will return an error.
shutdown(SSC)
causes all or part of a full-duplex connection to be terminated.
See the discussion on close and shutdown in
``Data transfer (Internet domain)''.
line 53-
This line closes the parent's file descriptor returned from accept.
Client (Internet domain)
The following code creates a
client that requests a connection from a listening server.
The manual page for each routine defines the necessary
#include files when calling that routine.
Sample client (part 1 of 2)
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <netinet/in.h>
4 #include <stdio.h>
5 #include <netdb.h>
6 #define PORTNUM 601
7 main(argc, argv)
8 int argc;
9 char *argv[];
10 {
11 int s;
12 struct sockaddr_in sin;
13 struct hostent *hp;
14 char buf[80];
15 if (argc != 2) {
16 printf("Illegal number of arguments");
17 exit(1);
18 }
19 if ((hp = gethostbyname(argv[1])) == 0) {
20 perror("tom: gethostbyname");
21 exit(1);
22 }
23 bzero(&sin, sizeof(sin));
24 bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
25 sin.sin_family = hp->h_addrtype;
lines 10-14-
Declarations are made here just as they are for the server,
except that line 13 declares hp to be a pointer to
a hostent structure.
lines 19-22-
A hostent structure containing
the IP number of the requested host is returned.
See
``Mapping host names (Internet domain)''
for details on how the host IP number is obtained.
lines 23-25-
The sin structure is cleared, the address of the
server is copied into it, and the family type (pointed to in
line 12), is copied from the hostent structure.
Sample client (part 2 of 2)
26 sin.sin_port = htons(PORTNUM);
27
28 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
29 perror("tom: socket");
30 exit(1);
31 }
32 if (connect(s, (struct sockaddr *) &sin, sizeof(sin), 0) == -1) {
33 perror("tom: connect");
34 exit(1);
35 }
36 sprintf(buf, "Hello world");
37 if (write(s, buf, sizeof(buf)) == -1) {
38 perror("tom: write");
39 exit(1);
40 }
41 close(s);
42 }
line 26-
The port number of the server is copied into sin.
lines 28-31-
A socket is created exactly as it was done for the server.
lines 32-35-
A connection request is accepted by the server
and a fully connected socket pair is established.
s refers to the client socket. &sin and
sizeof(sin) are pointers to the address family and
size of the other socket, that is, the server.
lines 36-40-
The client sends a message to the server, then terminates
its connection with the server.
s refers to the client socket,
while buf refers to the message length
specified in line 14.
line 41-
The client closes the socket descriptor obtained with the
socket call in line 28.
Next topic:
Datagrams in the Internet Domain
Previous topic:
Byte order
© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003