This appendix contains annotated files for a sample client/server program. Clients send a request to the server and print the server's response. Servers listen for client requests, print the request, and send a response to the client.
Although the program is not a real world application, it is structured demonstrate the sequence and use of the various socket calls.
The information is organized as follows:
You can find these programs and a protocol-independent client
in the/usr/examples/ipv6/network_programming
directory.
In addition, this section also contains sample output from these programs.
C.1 Programs Using AF_INET Sockets
This
section contains a client and server program that use AF_INET sockets.
C.1.1 Client Program Using AF_INET Sockets
Example C-1
shows
a sample client program that you can build, compile, and run on your system.
The program sends a request to and receives a response from the system specified
on the command line.
Example C-1: Client Stub Routine
/* * ***************************************************************** * * * * * Copyright (c) Compaq Computer Corporation, 2000 * * * * * * The software contained on this media is proprietary to * * * and embodies the confidential technology of Compaq * * * Computer Corporation. Possession, use, duplication or * * * dissemination of the software and media is authorized only * * * pursuant to a valid written license from Compaq Computer * * * Corporation. * * * * * * RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure * * * by the U.S. Government is subject to restrictions as set * * * forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, * * * or in FAR 52.227-19, as applicable. * * * * * ***************************************************************** */ #include <sys/types.h> #include <sys/socket.h> #include <sys/errno.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <arpa/inet.h> #define SERVER_PORT 7639 #define CLIENT_PORT 7739 #define MAXBUFSIZE 4096 int main ( int argc, char **argv ) { int s; char databuf[MAXBUFSIZE]; int dcount; struct sockaddr_in serveraddr; [1] struct sockaddr_in clientaddr; int serveraddrlen; const char *ap; const char *request = "this is the client's request"; struct hostent *hp; char *server; if (argc < 2) { printf("Usage: client <server>\n"); exit(1); } server = argv[1]; bzero((char *) &serveraddr, sizeof(struct sockaddr_in)); [2] serveraddr.sin_family = AF_INET; if ((hp = gethostbyname(server)) == NULL) { [3] printf("unknown host: %s\n", server); exit(2); } serveraddr.sin_port = htons(SERVER_PORT); while (hp->h_addr_list[0] != NULL) { if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { [4] perror("socket"); exit(3); } memcpy(&serveraddr.sin_addr.s_addr, hp->h_addr_list[0], hp->h_length); if (connect(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) { [5] perror("connect"); close(s); hp->h_addr_list++; continue; } break; } if (send(s, request, strlen(request), 0) < 0) { [6] perror("send"); exit(5); } dcount = recv(s, databuf, sizeof(databuf), 0); [7] if (dcount < 0) { perror("recv"); exit(6); } databuf[dcount] = '\0'; hp = gethostbyaddr((char *)&serveraddr.sin_addr.s_addr, [8] sizeof(serveraddr.sin_addr.s_addr), AF_INET); ap = inet_ntoa(serveraddr.sin_addr); [9] printf("Response received from"); if (hp != NULL) printf(" %s", hp->h_name); if (ap != NULL) printf(" (%s)", ap); printf(": %s\n", databuf); close(s); }
Declares
sockaddr_in
structures.
The use
of this type of structure is dictated by the communication domain of the socket
(AF_INET), which implies communication using the IPv4 protocol.
[Return to example]
Clears the server address and sets up server variables. The socket address for IPv4 communications is a 32-bit Internet address and a 16-bit port number. This will be the Internet address of the server and the port number on which it is listening. [Return to example]
Obtain the server's IPv4 address.
A call to
gethostbyname
returns IPv4 address only.
[Return to example]
Creates an AF_INET socket with a
socket
call.
The socket type SOCK_STREAM is specified for TCP or connection-oriented
communication.
[Return to example]
Connects to the server using the address in the
sockaddr_in
structure named
serveraddr
.
[Return to example]
Sends a request to the server. [Return to example]
Receives a response from the server. [Return to example]
Retrieves the server name using the address in the
sockaddr_in
structure named
serveraddr
.
A call
to
gethostbyaddr
expects an IPv4 address as input.
[Return to example]
Convert the server's 32-bit IPv4 address to a dot-formatted
Internet address text string.
A call to
inet_ntoa
expects
an IPv4 address as input.
[Return to example]
Example C-2
shows
a sample server program that you can build, compile, and run on your system.
The program receives requests from and sends responses to client programs
on other systems.
Example C-2: Server Stub Routine
/* * ***************************************************************** * * * * * Copyright (c) Compaq Computer Corporation, 2000 * * * * * * The software contained on this media is proprietary to * * * and embodies the confidential technology of Compaq * * * Computer Corporation. Possession, use, duplication or * * * dissemination of the software and media is authorized only * * * pursuant to a valid written license from Compaq Computer * * * Corporation. * * * * * * RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure * * * by the U.S. Government is subject to restrictions as set * * * forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, * * * or in FAR 52.227-19, as applicable. * * * * * ***************************************************************** */ #include <sys/types.h> #include <sys/socket.h> #include <sys/errno.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <arpa/inet.h> #define SERVER_PORT 7639 #define CLIENT_PORT 7739 #define MAXBUFSIZE 4096 int main ( int argc, char **argv ) { int s; char databuf[MAXBUFSIZE]; int dcount; struct sockaddr_in serveraddr; [1] struct sockaddr_in clientaddr; int clientaddrlen; struct hostent *hp; const char *ap; const char *response = "this is the server's response"; u_short port; if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { [2] perror("socket"); exit(1); } bzero((char *) &serveraddr, sizeof(struct sockaddr_in)); [3] serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); [4] serveraddr.sin_port = htons(SERVER_PORT); if (bind(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) { [5] perror("bind"); exit(2); } if (listen(s, SOMAXCONN) < 0) { [6] perror("Listen"); close(s); exit(3); while (1) { int new_s; clientaddrlen = sizeof(clientaddr); new_s = accept(s, (struct sockaddr *)&clientaddr, &clientaddrlen); [7] dcount = recv(new_s, databuf, sizeof(databuf), 0); [8] if (dcount <= 0) { perror("recv"); close(new_s); continue; } databuf[dcount] = '\0'; hp = gethostbyaddr((char *)&clientaddr.sin_addr.s_addr, [9] sizeof(clientaddr.sin_addr.s_addr), AF_INET); ap = inet_ntoa(clientaddr.sin_addr); [10] port = ntohs(clientaddr.sin_port); printf("Request received from"); if (hp != NULL) printf(" %s", hp->h_name); if (ap != NULL) printf(" (%s)", ap); printf(" port %d \"%s\"\n", port, databuf); if (send(new_s, response, strlen(response), 0) < 0) { [11] perror("send"); close(new_s); continue; } close(new_s); } close(s); }
Declares
sockaddr_in
structures.
The use
of this type of structure is dictated by the communication domain of the socket
(AF_INET), which implies communication using the IPv4 protocol.
[Return to example]
Creates an AF_INET socket. The socket type SOCK_STREAM is specified for TCP or connection-oriented communication. [Return to example]
Clears the server address and sets up server variables. The socket address for IPv4 communications is a 32-bit Internet address and a 16-bit port number. This will be the Internet address of the server and the port number on which it is listening. [Return to example]
Sets the server address to the IPv4 wildcard address INADDR_ANY. This signifies any attached network interface on the system. [Return to example]
Binds the server's address to the AF_INET socket. [Return to example]
Listens on the socket for a connection.
The server will queue
up to SOMAXCONN pending connections while it finishes processing the previous
accept
call.
See
sys_attrs_socket
(5)
Accepts a connection on this socket.
The
accept
call places the client's address in the
sockaddr_in
structure
named
clientaddr
.
[Return to example]
Receives data from the client. [Return to example]
Retrieves the client name using the address in the
sockaddr_in
structure named
clientaddr
.
A call
to
gethostbyaddr
expects an IPv4 address as input.
[Return to example]
Converts the client's 32-bit IPv4 address to a dot-formatted
Internet address text string.
A call to
inet_ntoa
expects
an IPv4 address as input.
[Return to example]
Sends a response to the client. [Return to example]
This section contains a client and server program that use AF_INET6
sockets.
C.2.1 Client Program Using AF_INET6 Sockets
Example C-3
shows a sample client program that you can build, compile, and run on your
system.
The program sends a request to and receives a response from the system
specified on the command line.
All addresses are in IPv6 address format.
Example C-3: Client Stub Routine
/* * ***************************************************************** * * * * * Copyright (c) Compaq Computer Corporation, 2000 * * * * * * The software contained on this media is proprietary to * * * and embodies the confidential technology of Compaq * * * Computer Corporation. Possession, use, duplication or * * * dissemination of the software and media is authorized only * * * pursuant to a valid written license from Compaq Computer * * * Corporation. * * * * * * RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure * * * by the U.S. Government is subject to restrictions as set * * * forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, * * * or in FAR 52.227-19, as applicable. * * * * * ***************************************************************** */ #include <sys/types.h> #include <sys/socket.h> #include <sys/errno.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <arpa/inet.h> #define SERVER_PORT 7639 #define CLIENT_PORT 7739 #define MAXBUFSIZE 4096 int main ( int argc, char **argv ) { int s; char databuf[MAXBUFSIZE]; int dcount; struct addrinfo *server_info; [1] struct addrinfo *cur_info; struct addrinfo hints; struct sockaddr_in6 serveraddr; [2] char addrbuf[INET6_ADDRSTRLEN]; char node[MAXDNAME]; char service[MAXDNAME]; int ni; int err; int serveraddrlen; const char *request = "this is the client's request"; char *server; if (argc < 2) { printf("Usage: client <server>\n"); exit(1); } server = argv[1]; bzero((char *) &hints, sizeof(hints)); [3] hints.ai_family = AF_INET6; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_ADDRCONFIG | AI_V4MAPPED; sprintf(service, "%d", SERVER_PORT); err = getaddrinfo(server, service, &hints, &server_info); [4] if (err != 0) { printf("%s\n", gai_strerror(err)); if (err == EAI_SYSTEM) perror("getaddrinfo"); exit(2); } cur_info = server_info; while (cur_info != NULL) { if ((s = socket(cur_info->ai_family, cur_info->ai_socktype, 0)) < 0) { [5] perror("socket"); freeaddrinfo(server_info); exit(3); } if (connect(s, cur_info->ai_addr, cur_info->ai_addrlen) <0 { [6] close(s); cur_info = cur_info->ai_next; continue; } break; } freeaddrinfo(server_info); [7] if (send(s, request, strlen(request), 0) < 0) { [8] perror("send"); exit(5); } dcount = recv(s, databuf, sizeof(databuf), 0); [9] if (dcount < 0) { perror("recv"); exit(6); } databuf[dcount] = '\0'; serveraddrlen = sizeof(serveraddr); if (getpeername(s, (struct sockaddr*) &serveraddr, &serveraddrlen) < 0) { [10] perror("getpeername"); exit(7); } printf("Response received from"); ni = getnameinfo((struct sockaddr*)&serveraddr, serveraddrlen, [11] node, sizeof(node), NULL, 0, NI_NAMEREQD); if (ni == 0) printf(" %s", node); ni = getnameinfo((struct sockaddr*)&serveraddr, serveraddrlen, [12] addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST); if (ni == 0) printf(" (%s)", addrbuf); printf(": %s\n", databuf); close(s); }
Declares
addrinfo
structures and the
hints
structure.
[Return to example]
Declares the
sockaddr_in6
structure.
The
use of this type of structure is dictated by the communication domain of the
socket (AF_INET6), which implies communication using the IPv6 protocol.
If
you wanted to write a protocol-independent program, you would declare a
sockaddr_storage
structure.
[Return to example]
Declares the address string buffer, node name string buffer, service name string buffer, error number variable, and server address length variable. [Return to example]
Clears the
hints
structure and sets up hints
variables.
Thehints
structure contains values that direct
the
getaddrinfo
processing.
In this case, AF_INET6 returns
IPv6 addresses.
The AI_ADDRCONFIG and AI_V4MAPPED values return AAAA records
if an IPv6 address is configured, and if none are found, return A records
if an IPv4 address is configured.
See
getaddrinfo
(3)hints
structure values.
[Return to example]
Obtains the server address.
A call to
getaddrinfo
returns IPv6-formatted addresses in one or more structures
of type
addrinfo
.
[Return to example]
Creates an AF_INET6 socket.
The socket type is specified in
the
addrinfo
structure.
[Return to example]
Connects to the server using the address in the
addrinfo
structure named
cur_info
.
[Return to example]
Frees all
addrinfo
structures.
[Return to example]
Sends a request to the server. [Return to example]
Receives a response from the server. [Return to example]
Obtains the address of the peer socket at the other end of
the connection and stores the address in a
sockaddr_in6
structure named
serverinfo
.
[Return to example]
Obtains the server's name with a call to
getnameinfo
using the address in the
sockaddr_in6
structure
named
serveraddr
.
The NI_NAMEREQD flag directs the routine
to return a host name for the given address.
[Return to example]
Obtains the server's numeric address value with a call to
getnameinfo
using the address in the
sockaddr_in6
structure named
serveraddr
.
The NI_NUMERICHOST flag directs
the routine to return an address value for the given address.
[Return to example]
Example C-4
shows a sample server program that you can build, compile, and run on your
system.
The program receives requests from and sends responses to client
programs on other systems.
Example C-4: Server Stub Routine
/* * ***************************************************************** * * * * * Copyright (c) Compaq Computer Corporation, 2000 * * * * * * The software contained on this media is proprietary to * * * and embodies the confidential technology of Compaq * * * Computer Corporation. Possession, use, duplication or * * * dissemination of the software and media is authorized only * * * pursuant to a valid written license from Compaq Computer * * * Corporation. * * * * * * RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure * * * by the U.S. Government is subject to restrictions as set * * * forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, * * * or in FAR 52.227-19, as applicable. * * * * * ***************************************************************** */ #include <sys/types.h> #include <sys/socket.h> #include <sys/errno.h> #include <netinet/in.h> #include <netdb.h> #include <string.h> #include <stdio.h> #include <signal.h> #include <stdlib.h> #include <arpa/inet.h> #define SERVER_PORT 7639 #define CLIENT_PORT 7739 #define MAXBUFSIZE 4096 int main ( int argc, char **argv ) { int s; char databuf[MAXBUFSIZE]; int dcount; struct sockaddr_in6 serveraddr; [1] struct sockaddr_storage clientaddr; [2] char addrbuf[INET6_ADDRSTRLEN]; char node[MAXDNAME]; char port[MAXDNAME]; int err; int ni; int clientaddrlen; const char *response = "this is the server's response"; if ((s = socket(AF_INET6, SOCK_STREAM, 0)) < 0) { [3] perror("socket"); exit(1); } bzero((char *) &serveraddr, sizeof(struct sockaddr_in6)); [4] serveraddr.sin6_family = AF_INET6; serveraddr.sin6_addr = in6addr_any; serveraddr.sin6_port = htons(SERVER_PORT); if (bind(s, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) { [5] perror("bind"); exit(2); } if (listen(s, SOMAXCONN) < 0) { [6] perror("listen"); close(s); exit(3); } while (1) { int new_s; clientaddrlen = sizeof(clientaddr); bzero((char *)&clientaddr, clientaddrlen); [7] new_s = accept(s, (struct sockaddr*)&clientaddr, &clientaddrlen); [8] if (new_s < 0) { perror("accept"); continue; } dcount = recv(new_s, databuf, sizeof(databuf), 0); [9] if (dcount < 0) { perror("recv"); close(new_s); continue; } databuf[dcount] = '\0'; printf("Request received from"); ni = getnameinfo((struct sockaddr *)&clientaddr, [10] clientaddrlen, node, sizeof(node), NULL, 0, NI_NAMEREQD); if (ni == 0) printf(" %s", node); ni = getnameinfo((struct sockaddr *)&clientaddr, [11] clientaddrlen, addrbuf, sizeof(addrbuf), port, sizeof(port), NI_NUMERICHOST|NI_NUMERICSERV); if (ni == 0) printf(" (%s) port %d", addrbuf, port); printf(" \"%s\"\n", port, databuf); if (send(new_s, response, strlen(response), 0) < 0) { [12] perror("send"); close(new_s); continue; } close(new_s); } close(s); }
Declares the
sockaddr_in6
structure named
serveraddr
.
The use of this type of structure is dictated by the
communication domain of the socket (AF_INET6), which implies communication
using the IPv6 protocol.
[Return to example]
Declares a
sockaddr_storage
structure named
clientaddr
.
The use of this type of structure enables your program
to be protocol independent.
[Return to example]
Creates an AF_INET6 socket. The socket type SOCK_STREAM is specified for TCP or connection-oriented communication. [Return to example]
Clears the server address and sets up the server variables. [Return to example]
Binds the server's address to the AF_INET socket. [Return to example]
Listens on the socket for a connection.
The server will queue
up to SOMAXCONN pending connections while it finishes processing the previous
accept
call.
See
sys_attrs_socket
(5)
Clears the client address. [Return to example]
Accepts a connection on this socket.
The
accept
call places the client's address in the
sockaddr_storage
structure named
clientaddr
.
[Return to example]
Receives data from the client. [Return to example]
Obtains the client's name with a call to
getnameinfo
using the address in the
sockaddr_storage
structure
named
clientaddr
.
The NI_NAMEREQD flag directs the routine
to return a host name for the given address.
[Return to example]
Obtains the client's numeric address value and port nnumber
with a call to
getnameinfo
using the address in the
sockaddr_storage
structure named
clientaddr
.
The NI_NUMERICHOST and NI_NUMERICSERV flags direct the routine to return a
values for the given address and the port number.
[Return to example]
Sends a response to the client. [Return to example]
This section contains sample output from the server and client programs.
The server program makes and receives all requests on an AF_INET6 socket
using
sockaddr_in6
.
For requests received over IPv4,
sockaddr_in6
contains an IPv4-mapped IPv6 address.
The following example shows the client program running on node
hostb6
and sending a request to node
hosta6
.
The program uses an AF_INET6 socket.
The
hosta6
node
has the IPv6 address 3ffe:1200::a00:2bff:fe97:7be0 in the Domain Name System
(DNS).
user2@hostb6> ./client hosta6 Response received from hosta6.ipv6.corp.example (3ffe:1200::a00:2bff:fe97:7be0): this is the server's response
On the server node,
the following example shows the server program invocation and the request
received from the client node
hostb6
:
user1@hosta6> ./server Request received from hostb6.ipv6.corp.example (3ffe:1200::a00:2bff:fe2d:02b2 port 7739 "this is the client's request"
The following example shows the client program running on node
hostb
and sending a request to node
hosta
.
The
program uses an AF_INET6 socket.
The
hosta
node has the
IPv4 address 10.10.10.13 in the DNS.
user2@hostb> ./client hosta Response received from hosta.corp.example (::ffff:10.10.10.13): this is the server's response
On the server node, the following
example shows the server program invocation and the request received from
the client node
hostb
:
user1@hosta6> ./server Request received from hostb.corp.example (::ffff:10.10.10.251) port 7739 "this is the client's request"
The following example shows the client program running on node
hostc
and sending a request to node
hosta
.
The
program was built and run on an IPv4-only system using an AF_INET socket.
user3@hostc> ./client hosta Response received from hosta.corp.example (10.10.10.13): this is the server's response
On the server node, the following
example shows the server program invocation and the request received from
the client node
hostc
:
user1@hosta6> ./server Request received from hostc.corp.example (::ffff:10.10.10.63) port 7739 "this is the client's request"