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
gethostbyaddrexpects 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
gethostbyaddrexpects 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"