jmay@bbn.com (Jason May) (07/29/88)
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 <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); }
cookson@mbunix.mitre.org (Cookson) (02/03/90)
I'm trying to learn how to use sockets for interprocess communication, both on a single machine, and across a net. Can anyone recomend a good source for me to read? Thanks in advance Dean cookson@mbunix.mitre.org
gt0178a@prism.gatech.EDU (BURNS,JIM) (07/21/90)
A while back, Patrick Spinler posted a sockets program that he was having trouble with and asked for email replies. I sent him the mail below asking for his results and it bounced. Would appreciate email OR a post (especially if YOU bounce). From MAILER-DAEMON@prism.gatech.edu Fri Jul 20 22:00:12 1990 Return-Path: <MAILER-DAEMON@prism.gatech.edu> Received: by hydra.gatech.edu (5.61/3.1) id AA06120; Fri, 20 Jul 90 21:50:48 -0400 Date: Fri, 20 Jul 90 21:50:48 -0400 From: MAILER-DAEMON@prism.gatech.edu (Mail Delivery Subsystem) Subject: Returned mail: Cannot send message for 5 days Message-Id: <9007210150.AA06120@prism.gatech.edu> To: gt0178a@prism.gatech.edu Status: RO ----- Transcript of session follows ----- 421 att1.mankato.msus.edu.cether... Deferred: Connection timed out during user open with att1.mankato.msus.edu ----- Unsent message follows ----- Return-Path: <gt0178a@prism.gatech.edu> Received: by hydra.gatech.edu (5.61/3.1) id AA15925; Sun, 15 Jul 90 21:55:38 -0400 Date: Sun, 15 Jul 90 21:55:38 -0400 From: gt0178a@prism.gatech.edu (BURNS,JIM) Message-Id: <9007160155.AA15925@prism.gatech.edu> To: pspinler@att1.mankato.msus.edu Subject: Re: question about using sockets on sysVr3 pspinler@att1.mankato.msus.edu (Patrick J. Spinler): > I am attempting to learn to use sockets, however, I am evidently > creating a protocal error of some sort, and have no real idea where to > start looking. If some kind soul would please tell me why I'm getting > an EINVAL error on my call to bind(), I would be very grateful. I'm Did you ever get an answer to your question, and can you forward same to me? I would prefer working code and an explanation of the changes. I got past your bind error by commenting out the bcopy just before, but then the connection never established, and timed-out. Thanx, Jim Burns -- BURNS,JIM Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332 uucp: ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a Internet: gt0178a@prism.gatech.edu
gt0178a@prism.gatech.EDU (BURNS,JIM) (07/21/90)
in article <11639@hydra.gatech.EDU>, gt0178a@prism.gatech.EDU (BURNS,JIM) says:
A while back, Patrick Spinler posted a sockets program that he was having
trouble with and asked for email replies. I sent him the mail below asking
for his results and it bounced. Would appreciate email OR a post
(especially if YOU bounce).
Sorry - Please ignore this message - I posted it to the wrong group.
--
BURNS,JIM
Georgia Institute of Technology, Box 30178, Atlanta Georgia, 30332
uucp: ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!gt0178a
Internet: gt0178a@prism.gatech.edu
ciancarini-paolo@cs.yale.edu (paolo ciancarini) (04/22/91)
I would like to pass a socket from a process to another; the two processes in general are unrelated (they could even be on different machines, say sharing an NSF FS). To be a little more concrete, I have a concurrent server that uses a connection-oriented protocol using the sequence: socket/bind/listen/accept/fork. I have other processes, not created by the server, that would like to get the particular socket obtained after accept. So, is it possible to pass such a socket among unrelated processes? Please answer by E-mail. I will summarize if there is any interest (and any answer!). Paolo Ciancarini
wayne@jahangir.UUCP (wayne) (05/24/91)
I am just starting to expirement with sockets. I have a small program below which I cannot get to work for some reason. I took it almost verbatum from W. Richard Stevens book "UNIX Network Programming" What happens is the client and server fail to connect for some reason. Can anyone out there tell me what I am doing wrong? My hardware is a MIPS Magnum 3000.
subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (05/24/91)
In article <556@jahangir.UUCP> wayne@jahangir.UUCP (wayne) writes: > > > I am just starting to expirement with sockets. I have a small program >below which I cannot get to work for some reason. I took it almost verbatum >from W. Richard Stevens book "UNIX Network Programming" > > What happens is the client and server fail to connect for some reason. >Can anyone out there tell me what I am doing wrong? > > My hardware is a MIPS Magnum 3000. Sure. The problem is line 79 of /u/wayne/foo/bar/socket/test.c. Put a space before the comment at the end of that line, and your program will work :-) Seriously, why don't you post what your code to the net so people can see exactly WHAT it is. We're not mindreaders, ya know. -Kartik -- internet% ypwhich subbarao@phoenix.Princeton.EDU -| Internet kartik@silvertone.Princeton.EDU (NeXT mail) SUBBARAO@PUCC.BITNET - Bitnet
wayne@jahangir.UUCP (wayne) (06/29/91)
Here's on for all you sockets fans out there. I have stream sockets. One process creates and binds to the socket. Another process connects to the socket. If something bad happens and both processes exit without closing the socket, is there a way to close the socket. The process that bound the socket has not properly closed it. And the reading process has died. In effect leaving a orphaned socket. Can you get rid of this thing short of rebooting?
brnstnd@kramden.acf.nyu.edu (Dan Bernstein) (06/29/91)
In article <564@jahangir.UUCP> wayne@jahangir.UUCP (wayne) writes: > Here's on for all you sockets fans out there. I have stream > sockets. One process creates and binds to the socket. Another process > connects to the socket. > If something bad happens and both processes exit without closing > the socket, is there a way to close the socket. The process that bound > the socket has not properly closed it. And the reading process has died. > In effect leaving a orphaned socket. When a process dies, all its descriptors are closed. If every process that had the socket open suddenly dies, the socket is closed. I suspect that you're working with UNIX-domain sockets, and what you're seeing is the useless socket file left after the server dies. You can just remove it. If the socket was for meant for just that connection, the server should remove the bound filename immediately after accept(). In any case it should make an effort to catch those ``bad'' things happening and remove the socket before it exits. ---Dan