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