HPlogo HP 9000 Networking: BSD Sockets Interface Programmer's Guide > Chapter 6 Using UNIX Domain Stream Sockets

Example Using UNIX Domain Stream Sockets

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Glossary

 » Index

NOTE: These programs are provided as examples only of UNIX Domain stream socket usage and are not Hewlett-Packard supported products.

These programming examples demonstrate how to set up and use UNIX Domain stream sockets. These sample programs can be found in the /usr/lib/demos/networking/af_unix directory. The client program is intended to run in conjunction with the server program.

This example shows how to create UNIX Domain stream sockets and how to set up address structures for the sockets. In this example the client process sends 2000 bytes of data to the server (five times). The server process can receive data from any other process and will echo the data back to the sender.

/*
* Sample Program: AF_UNIX stream sockets, server process
*
* CATCH - RECEIVE DATA FROM THE PITCHER
*
* Pitch and catch set up a simple unix domain stream socket
* client-server connection. The client (pitch) then sends
* data to server (catch), throughput is calculated, and the
* result is printed to the client's stdout.
*/
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCKNAME "/tmp/p_n_c"
#define BUFSIZE 32*1024-1
int timeout();
int s; /* server socket */
char buffer[BUFSIZE];
struct bullet {
int bytes;
int throughput;
int magic;
} bullet = { 0, 0, 0 };

send_data(fd, buf, buflen)
char *buf;
{
int cc;
while (buflen > 0) {
cc = send(fd, buf, buflen, 0);
if (cc == -1) {
perror("send");
exit(0);
}
buf += cc;
buflen -= cc;
}
}
recv_data(fd, buf, buflen)
char *buf;
{
int cc;
while (buflen > 0) {
cc = recv(fd, buf, buflen, 0);
if (cc == -1) {
perror("recv");
exit(0);
}
buf += cc;
buflen -= cc;
}
}
main(argc, argv)
int argc;
char *argv[];
{
int bufsize, bytes, cc, i, total, pid, counter_pid;
float msec;
struct timeval tp1, tp2;
int ns, recvsize, secs, usec;
struct timezone tzp;
struct sockaddr_un sa;
/*
* The SIGPIPE signal will be received if the peer has gone away
* and an attempt is made to write data to the peer. Ignoring this
* signal causes the write operation to receive an EPIPE error.
* Thus, the user is informed about what happened.
*/
signal(SIGPIPE, SIG_IGN);
signal(SIGCLD, SIG_IGN);
signal(SIGINT, timeout);
setbuf(stdout, 0);
setbuf(stderr, 0);
if (argc > 1) {
argv++;
counter_pid = atoi(*argv++);
} else
counter_pid = 0;
/*
* Set up the socket variables - address family, socket name.
* They'll be used later to bind() the name to the server socket.
*/
sa.sun_family = AF_UNIX;
strncpy(sa.sun_path, SOCKNAME,
(sizeof(struct sockaddr_un) - sizeof(short)));
/*
* Create the server socket
*/
if ((s = socket( AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("catch - socket failed");
exit(0);
}
bufsize = BUFSIZE;
/*
* Use setsockopt() to change the socket buffer size to improve
* throughput for large data transfers
*/
if ((setsockopt(s, SOL_SOCKET, SO_RCVBUF, &bufsize,
sizeof(bufsize)))
== -1) {
perror("catch - setsockopt failed");
exit(0);
}
/*
* Bind the server socket to its name
*/
if ((bind(s, &sa, sizeof(struct sockaddr_un))) == -1) {
perror("catch - bind failed");
exit(0);
}
/*
* Call listen() to enable reception of connection requests
* (listen() will silently change given backlog 0, to be 1 instead)
*/
if ((listen(s, 0)) == -1) {
perror("catch - listen failed");
exit(0);
}next_conn:
i = sizeof(struct sockaddr_un);
/*
* Call accept() to accept connection request. This call will block
* until a connection request arrives.
*/
if ((ns = accept(s, &sa, &i)) == -1) {
if (errno == EINTR)
goto next_conn;
perror("catch - accept failed");
exit(0);
}
if ((pid = fork()) != 0) {
close(ns);
goto next_conn;
}
/*
close(s);
*/
/*
* Receive the bullet to synchronize with the other side
*/
recv_data(ns, &bullet, sizeof(struct bullet));
if (bullet.magic != 12345) {
printf("catch: bad magic %d\n", bullet.magic);
exit(0);
}
bytes = bullet.bytes;
recvsize = (bytes>BUFSIZE)?BUFSIZE:bytes;
/*
* Send the bullet back to complete synchronization
*/
send_data(ns, &bullet, sizeof(struct bullet));
cc = 0;
if (counter_pid)
kill(counter_pid, SIGUSR1);
if (gettimeofday(&tp1, &tzp) == -1) {
perror("catch time of day failed");
exit(0);
}
/*
* Receive data from the client
*/
total = 0;
i = bytes;
while (i > 0) {
cc = recvsize < i ? recvsize : i;
recv_data(ns, buffer, cc);
total += cc;
i -= cc;
}
/*
* Calculate throughput
*/
if (gettimeofday(&tp2, &tzp) == -1) {
perror("catch time of day failed");
exit(0);
}
if (counter_pid)
kill(counter_pid, SIGUSR2);
secs = tp2.tv_sec - tp1.tv_sec;
usec = tp2.tv_usec - tp1.tv_usec;
if (usec < 0) {
secs ;
usec += 1000000;
}
msec = 1000*(float)secs;
msec += (float)usec/1000;
bullet.throughput = bytes/msec;
/*
* Send back the bullet with throughput info, then close the
* server socket
*/
if ((cc = send(ns, &bullet, sizeof(struct bullet), 0)) == -1) {
perror("catch - send end bullet failed");
exit(0);
}
close(ns);
}
timeout()
{
printf( "alarm went off -- stopping the catch process\n");
fprintf(stderr, "stopping the catch process\n");
unlink(SOCKNAME);
close(s);
exit(6);
}
/*
* Sample Program : AF_UNIX stream sockets, client process
*
* PITCH - SEND DATA TO THE CATCHER
*
* Pitch and catch set up a simple unix domain stream socket
* client-server connection. The client (pitch) then sends
* data to the server (catch), throughput is calculated, and
* the result is printed to the client's stdout.
*/
#include <stdio.h>
#include <time.h>
#include <netdb.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#define SOCKNAME "/tmp/p_n_c"
#define BUFSIZE 32*1024-1
char buffer[BUFSIZE];
struct bullet {
int bytes;
int throughput;
int magic;
} bullet = { 0, 0, 12345 };
send_data(fd, buf, buflen)
char *buf;
{
int cc;
while (buflen > 0) {
cc = send(fd, buf, buflen, 0);
if (cc == -1) {
perror("send");
exit(0);
}
buf += cc;
buflen -= cc;
}
}
recv_data(fd, buf, buflen)
char *buf;
{
int cc;
while (buflen > 0) {
cc = recv(fd, buf, buflen, 0);
if (cc == -1) {
perror("recv");
exit(0);
}
buf += cc;
buflen -= cc;
}
}
main( argc, argv)
int argc;
char *argv[];
{
int bufsize, bytes, cc, i, total, pid;
float msec;
struct timeval tp1, tp2;
int s, sendsize, secs, usec;
struct timezone tzp;
struct sockaddr_un sa;
/*
* The SIGPIPE signal will be received if the peer has gone away
* and an attempt is made to write data to the peer. Ignoring
* the signal causes the write operation to receive an EPIPE error.
* Thus, the user is informed about what happened.
*/
signal(SIGPIPE, SIG_IGN);
setbuf(stdout, 0);
setbuf(stderr, 0);
if (argc < 2) {
printf("usage: pitch Kbytes [pid]\n");
exit(0);
}
argv++;
/*
* Set up socket variables (address family; name of server socket)
* (they'll be used later for the connect() call)
*/
sa.sun_family = AF_UNIX;
strncpy(sa.sun_path, SOCKNAME,
(sizeof(struct sockaddr_un) - sizeof(short)));
bullet.bytes = bytes = 1024*atoi(*argv++);
if (argc > 2)
pid = atoi(*argv++);
else
pid = 0;
sendsize = (bytes < BUFSIZE) ? bytes : BUFSIZE;
/*
* Create the client socket
*/
if ((s = socket( AF_UNIX, SOCK_STREAM, 0)) == -1) {
perror("pitch - socket failed");
exit(0);
}
bufsize = BUFSIZE;
/*
* Change the default buffer size to improve throughput for
* large data transfers
*/
if ((setsockopt(s, SOL_SOCKET, SO_SNDBUF, &bufsize,
sizeof(bufsize)))
== -1) {
perror("pitch - setsockopt failed");
exit(0);
}
/*
* Connect to the server
*/
if ((connect(s, &sa, sizeof(struct sockaddr_un))) == - 1) {
perror("pitch - connect failed");
exit(0);
}
/*
* send and receive the bullet to synchronize both sides
*/
send_data(s, &bullet, sizeof(struct bullet));
recv_data(s, &bullet, sizeof(struct bullet));
cc = 0;
if (pid)
kill(pid,SIGUSR1);
if (gettimeofday(&tp1, &tzp) == -1) {
perror("pitch time of day failed");
exit(0);
}
i = bytes;
total = 0;
/*
* Send the data
*/
while (i > 0) {
cc = sendsize < i ? sendsize : i;
send_data(s, buffer, cc);
i -= cc;
total += cc;
}
/*
* Receive the bullet to calculate throughput
*/
recv_data(s, &bullet, sizeof(struct bullet));
if (gettimeofday(&tp2, &tzp) == -1) {
perror("pitch time of day failed");
exit(0);
}
if (pid)
kill(pid, SIGUSR2);
/*
* Close the socket
*/
close(s);
secs = tp2.tv_sec - tp1.tv_sec;
usec = tp2.tv_usec - tp1.tv_usec;
if (usec < 0) {
secs;
usec += 1000000;
}
msec = 1000*(float)secs;
msec += (float)usec/1000;
printf("PITCH: %d Kbytes/sec\n", (int)(bytes/msec));
printf("CATCH: %d Kbytes/sec\n", bullet.throughput);
printf("AVG: %d Kbytes/sec\n",
((int)(bytes/msec)+bullet.throughput)/2);
}
© 1997 Hewlett-Packard Development Company, L.P.