steven@pearl.berkeley.edu (Stephen the Greatest) (05/07/87)
Thank you guys for all your great help. The first problem is solved. There are, however, some more things I would like to clearify about sockets. All I need to do is to have communications between two processes (which are spawned separately). How does the processes know where to connect to? Also, I would like some form of interrupt-driven mechanism to signal one process when a message arrives. I don't want to keep polling the socket for that will eat up cpu time. Is there any way to cause a process to sleep when the socket is empty and wakes up when new messages arrive? Thanx for all your help. By the way, we are running 4.3 BSD here. I will get to the Primer on Interprocess Communications later. - Stephen
edw@ius2.cs.cmu.edu (Eddie Wyatt) (05/07/87)
Here's one way to generate an interrupt over a socket. first initialization: /************************************************************************** * * * Ninit * * * ************************************************************************** Purpose : This function initializes the client network connection with the LMB. If the module can not bind to the socket it will try every second until it can. Also determining whether byte swapping is needed and synchronizing the clocks in done here. Programmer : Tony Stenz (Eddie Wyatt) Date : ? (January 1987) Input : name - the name one wants to give to the module Output : None Locals : h, sp, sin - all used in establishing the connection hostname - the name of the computer the LMB resides on Globals : port - is modified to be the file descriptor for the connection between the LMB and the module ************************************************************************/ Ninit(name) char *name; { struct hostent *h; struct servent *sp; struct sockaddr_in sin; char hostname[80]; if ((sp = getservbyname(SERVERNAME, "tcp")) == 0) signalerror("Ninit",NENOSERVER,FATAL,SERVERNAME); endservent(); if (getenv(LMBHOSTENV) != NULL) (void) strcpy(hostname,getenv(LMBHOSTENV)); else { (void) printf("Enter host name for LMB: "); (void) scanf("%s", hostname); clearline(); } do { if ((h = gethostbyname(hostname)) != 0) break; signalerror("Ninit",NENOHOST,WARNING,hostname); (void) printf("Enter host name for LMB: "); (void) scanf("%s", hostname); clearline(); } while (TRUE); endhostent(); (void) printf("Waiting to connect to LMB on %s\n",hostname); do { if ((port = socket(AF_INET, SOCK_STREAM, 0)) < 0) signalerror("Ninit",NENOSOCKET,FATAL); bzero((char *) & sin, sizeof(sin)); bcopy(h->h_addr, (char *) &sin.sin_addr, h->h_length); sin.sin_family = h->h_addrtype; sin.sin_port = sp->s_port; if (connect(port,&sin, sizeof(sin)) >= 0) break; (void) close (port); sleep(1); } while (TRUE); enable_sspec_interrupts(); BBCONVERT = (SWAP_NUM != Nreceiveint()); sync_clocks(); Nsendmodname(name); (void) printf("Connection established with LMB.\n"); } Enabling interrupts : /************************************************************************** * * * enable_sspec_interrupts * * * ************************************************************************** Purpose : This function enables SIGURG interrupts to be generated on the port that connects the LMB and module. Also the interrupt handle is setup for the interrupt. Programmer : Eddie Wyatt Date : January 1987 Input : None Output : None Locals : None pgrp - the process group id of the module (used to enable SIGURG interrupts to be generate at this end of the connection) Globals : port - not modified ************************************************************************/ enable_sspec_interrupts() { int pgrp = -getpid(); (void) signal(SIGURG,urgent_message_processor); (void) ioctl(port,SIOCSPGRP, (char *) &pgrp); } urgent message processor : /************************************************************************** * * * urgent_message_processor * * * ************************************************************************** Purpose : This function is call when a SIGURG interrupt is sent to the module. An SIGURG is sent to the module to notify the module that a standing spec token has arrived and that the module should mediately stop what it is doing and start processing the standing spec token. How this is actually done is by setting up this routine as the interrupt handler for the signal SIGURG using the UNIX system call "signal". The "recv" call is used to read a single character which has no meaning that was sent out of bound (OOB) by the LMB to generate a SIGURG interrupt at this end of the communications. Programmer : Eddie Wyatt Date : January 1987 Input : sig - is which interrupt us generate to cause this function call code - is additional information about the interrupt scp - is a point to a structure which is used by the operating system to restore the context from before the signal Output : None Locals : ch - used to read character send out of bounds to generate SIGURG msgtype - message type of the current message on the port connecting the LMB and module (might not always be SENDSTANDINGSPEC) Globals : port - not modified ************************************************************************/ int urgent_message_processor(sig, code, scp) int sig, code; struct sigcontext *scp; { char ch; int msgtype; (void) recv(port,&ch,sizeof(char),MSG_OOB); msgtype = ready_to_read(port) ? peek_at_port() : UNKNOWN; if ((msgtype == M_SENDSTANDINGLIST) || (msgtype == M_KILL)) (void) Nreceive_message(M_SENDSTANDINGLIST); } -- Eddie Wyatt e-mail: edw@ius2.cs.cmu.edu