Sockets

Jason May jmay at bbn.com
Fri Jul 29 07:09:29 AEST 1988


Thanks to those people that sent me information in response to
my question concerning sockets a couple of weeks back.  For
the interest and edification of those and any others, here is
a working example of socket use.

There are two files here.  I don't know how to make my own shar
files, so I've just stuck the files at the end of this message.
The two files are a server and a client - the server will
accept connections from up to MAXCLIENTS different clients and can carry
on conversations with all of them and not get them confused.
The code is not the most beautiful imaginable, and there are lots
of other things that could be done here, but this stuff at least
works (under Ultrix, that is, and presumable BSD and others).

Jason
(jmay at alexander.bbn.com)


=====================
server.c
=====================

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define TRUE 1
#define FALSE 0

#define PORT 0x1234
#define ADDRSIZE sizeof (SOCK)
#define MAXCLIENTS 4

typedef struct sockaddr_in SOCK;
SOCK server;

typedef struct {
    SOCK *client;
    char *text;
} MESSAGE;

int create_server ();
MESSAGE *server_recv (/* sd */);
int server_send (/* sd, client, message */);
void done_server ();
int find_client (/* client * */);
int find_free_client ();

int numclients = 0;
SOCK client[MAXCLIENTS+1];
MESSAGE message;


void main()
{
    int sd;
    int flag = TRUE, ok = TRUE;
    int i;
    MESSAGE *msg;
    int clinum;

    bzero (client, ADDRSIZE * MAXCLIENTS);

    if ((sd = create_server ()) == -1)
	exit (1);

    while (flag) {
	msg = server_recv (sd);
	ok = TRUE;

	if ( (clinum = find_client (msg->client)) == -1)
	  if ( (clinum = find_free_client ()) == -1) {
	      printf ("No space for a new client; %d clients allocated\n",
		      numclients);
	      ok = FALSE;
	      bcopy (msg->client, &(client[MAXCLIENTS]), ADDRSIZE);
	      server_send (sd, MAXCLIENTS, "End");
	      numclients++;
	  }
	  else {
	      bcopy (msg->client, &(client[clinum]), ADDRSIZE);
	      printf ("Server: Allocating slot %d to client.\n", clinum);
	  }

	if (ok) {
	    printf ("Server: Rcvd '%s' from client %d [%d.%d.%d.%d, %x]\n",
		    msg->text, clinum, msg->client->sin_addr.s_net,
		    msg->client->sin_addr.s_host, msg->client->sin_addr.s_lh,
		    msg->client->sin_addr.s_impno, msg->client->sin_port);
	    flag = server_send (sd, clinum, msg->text);
	}
    }	
    done_server (sd);
}


int create_server ()
{
    int sd;

    if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
	perror ("Server: socket");
	return (-1);
    }

    bzero (server, ADDRSIZE);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons (PORT);

    if (bind (sd, &server, ADDRSIZE) == -1) {
	perror ("Server: bind");
	return (-1);
    }

    return (sd);
}


MESSAGE *server_recv (sd)
int sd;
{
    static SOCK cli;
    int addrlen = ADDRSIZE;
    static char text[100];
    int clinum;

    bzero (text, sizeof (text));

    if (recvfrom (sd, text, sizeof (text), 0, &cli, &addrlen) == -1) {
	perror ("Server: recv");
	return (NULL);
    }

    message.client = &cli;
    message.text = text;

    return (&message);
}

int server_send (sd, clinum, msg)
int sd;
int clinum;
char *msg;
{
    if (sendto (sd, msg, strlen (msg), 0, &(client[clinum]), ADDRSIZE) == -1) {
	perror ("Server: sendto");
	return (-1);
    }

    if (strcmp (msg, "End") == 0) {
	client[clinum].sin_family = 0;
	numclients--;
	if (numclients == 0)
	  return (FALSE);
	else
	  return (TRUE);
    }
    else
      return (TRUE);
}


void done_server (sd)
int sd;
{
    close (sd);
}


int find_client (cli)
SOCK *cli;
{
    int i;

    for  ( i=0; (bcmp (&(client[i]), cli, ADDRSIZE) != NULL) &&
	   (i < MAXCLIENTS); i++ );

    if (i >= MAXCLIENTS)
      return (-1);
    else
      return (i);
}


int find_free_client ()
{
    int i;

    for ( i=0; (client[i].sin_family != 0) && (i < MAXCLIENTS); i++ );

    if (i >= MAXCLIENTS)
      return (-1);
    else {
	numclients++;
	return (i);
    }
}

=====================================
client.c
=====================================

#include <stdio.h>
#include <sys/types.h>
#include <curses.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

#define PORT 0x1234
#define HOST "serverhost"	/* replace this */
#define ADDRSIZE sizeof (struct sockaddr_in)

int setup_sockets (/* hostname, port, server */);
int mysend (/* sd, server, msg */);
char *myrecv (/* sd, server */);
void client_done ();

struct sockaddr_in server;

void main ()
{
    int sd;
    char to_server[80];
    char *from_server;
    int flag = 1;

    if ( (sd = setup_sockets (HOST, PORT, &server)) == -1)
      exit (1);

    while (flag) {
	printf ("Enter: ");
	gets (to_server);
	if (mysend (sd, &server, to_server) != -1)
	  printf ("Client: Received '%s' from server\n",
		  from_server = myrecv (sd, &server));
	if (strcmp (from_server, "End") == NULL)
	  flag = 0;
    }
    client_done (sd);
}


int setup_sockets (hostname, port, server)
char *hostname;
int port;
struct sockaddr_in *server;
{
    int sd;
    struct hostent *hp;

    if ((hp = gethostbyname (hostname)) == 0) {
	perror ("Client: gethostbyname");
	return (-1);
    }

    bzero (server, ADDRSIZE);
    server->sin_family = AF_INET;
    server->sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
    server->sin_port = htons (port);
    
    if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == -1) {
	perror ("socket:");
	return (-1);
    }
    return (sd);
}


int mysend (sd, server, msg)
int sd;
struct sockaddr_in *server;
char *msg;
{
    int count;

    if ((count = sendto (sd, msg, strlen (msg), 0, server, ADDRSIZE)) == -1) {
	perror ("Client: sendto");
	return (-1);
    }
    return (count);
}


char *myrecv (sd, server)
int sd;
struct sockaddr_in *server;
{
    int addrlen = ADDRSIZE;
    static char msg[100];
    int msglen;

    if (recvfrom (sd, msg, msglen, 0, server, &addrlen) == -1) {
	perror ("Client: recv");
	return (NULL);
    }
    msg[msglen] = 0;
    return (msg);
}


void client_done (sd)
int sd;
{
    if (shutdown (sd, 2) == -1) {
	perror ("Client: shutdown");
	exit (1);
    }

    close (sd);
}



More information about the Comp.unix.questions mailing list