Path: utzoo!utgpu!attcan!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!pasteur!ames!mailrus!husc6!bbn!bbn.com!jmay From: jmay@bbn.com (Jason May) Newsgroups: comp.unix.questions Subject: Sockets Message-ID: <27638@bbn.COM> Date: 28 Jul 88 21:09:29 GMT Sender: news@bbn.COM Reply-To: jmay@BBN.COM () Organization: Bolt Beranek and Newman Inc., Cambridge MA Lines: 313 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@alexander.bbn.com) ===================== server.c ===================== #include #include #include #include #include #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 #include #include #include #include #include #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); }