Interrupt driven socket -read and write
Raman Kannan
kannan at b.cs.wvu.wvnet.edu
Wed Apr 19 00:05:10 AEST 1989
The problem I am trying to solve is to be interrupted when
there is something to read from a socket.
I am using signal (SIGIO, handler_function).
Within that handler I do the following:
reset my interrupt
accept --- check for errors and get the file descriptor
read on the fd. -- check for errors
return ; hoping to get back to place where the main was interrupted.
The trouble I am having:
It does not return to the main after the call to accept.
OBSERVED:
Multiple interrupts trigger the handler function. I put some
print stmts to check it.
If I return before the accept call, the main loop comes back to
life.
Can soemone point out the problem. Thank you very much in advance.
---==== The following is the source
/* sock header has socket and fcntl include
and a couple of int definitions */
#include "sock_header.h"
#include <signal.h>
/*
this code listens on a socket
and writes out on stdio.
Quits when the message recd is ENDING ALL CONNECTIONS
*/
int rval, sock , msgsock , length ;
struct sockaddr_in name ;
int buf_count ;
/*****************
THIS IS COMMON BLOCK
*****************/
/* the kb_buffer holds the recd message until it is processed */
char kb_buffer [10] [1024] ;
/* the r_id indicates the next buffer to be used for reading
the w_id indicates the next buffer to ne used for writing
the kbstatus indicates the current status of the next
buffer
0 => has been read and can be written over
1 => has been written and must be read before writing
*/
int r_id , w_id , kbstatus [10] ;
/*****************
END OF COMMON BLOCK
*****************/
char buf [1024], rd_buf [1024] ;
/* set all buffers to be written
A buffer can be written only if the content has been read
*/
initialize_buffers ()
{
int i = 0 ;
for (; i < 10 ; ) kbstatus [i++] = HAS_BEEN_READ ;
r_id = w_id = 0 ;
}
int io_handler ()
{
/* when a signal is raised
it resets to default
so set it back to our handler */
signal ( SIGIO, io_handler ) ;
if ( kbstatus[w_id] ) {
printf ("\n all buffers full ");
return ;}
msgsock = accept ( sock , (struct sockaddr *)0 , (int *) 0) ;
buf_count = 0 ;
if ( msgsock == -1 ) { perror ("accept") ;
exit (1) ;
}
/* a connection has been accepted
clear the next write buffer */
bzero ( kb_buffer[w_id] , LCM_BLOCK_SIZE ) ;
printf ("\n In INTERRUPT HANDLER\n");
bzero ( rd_buf , LCM_BLOCK_SIZE ) ;
if ( (rval = read ( msgsock , rd_buf, LCM_BLOCK_SIZE ))< 0 ) {
perror ("READING STREAM SOCKET") ;
exit (0) ; }
else if ( rval != 0 ) {
/* place it in a buffer for processing by the main module */
strcat ( kb_buffer[w_id] , rd_buf ) ;
printf ("\n<%s>", rd_buf ) ;
printf ("\n<kb_buffer =>%s>", kb_buffer[w_id]);
buf_count += rval ;
/* printf ("\n--> %s \n",rd_buf ) ;*/
}
/* indicate that this buffer buffer is not yet read */
printf ("\nbuffer being written is <%d>",w_id);
kbstatus [w_id] = 1 ;
/* next buffer */
if ( ++w_id == 10 ) w_id = 0 ;
close (msgsock ) ;
printf ("\nreturning from interrupt");
return rval ;
}/* returning from interrrupt */
main ()
{
initialize_buffers () ;
sock = socket ( AF_INET , SOCK_STREAM , 0 ) ;
if ( sock < 0 ) {
perror ( "opening SOCK_STREAM socket");
exit (1) ;
}
name.sin_family = AF_INET ;
name.sin_addr.s_addr = INADDR_ANY ;
name.sin_port = READ_SOCK ;
if ( bind ( sock ,(struct sockaddr *) &name , sizeof name ) < 0 )
{
perror ("binding STREAM SOCKET");
exit (1) ;
}
/* set up interrupt for reading on sock */
signal ( SIGIO, io_handler ) ;
/* set th eprocess receving the SIGIO/SIGURG signal to us */
if ( fcntl ( sock , F_SETOWN , getpid () ) < 0 ) {
perror ("COULDNT SET OWNER FOR THE SIGURG");
exit (1) ;
}
/* allow receipt of asynchrouns I/O signal */
if ( fcntl ( sock , F_SETFL , FASYNC ) < 0 ) {
perror ("COULDNT SET asynchrnous I/O");
exit (1) ;
}
listen ( sock , 5 ) ;
do {
/* the r_id refers to next buffer in the ring
if it is the end of the ring reset it to the
beginning of the buffer */
if ( r_id == 10 ) r_id = 0 ;
printf ("\n< MAIN LOOP WORKING>\n");
printf ("\nbuffer being checked is <%d>",r_id);
if ( kbstatus [ r_id ] )
{ /* something has been written into this buffer
let us process it */
printf ("\n< SOMETHING CAME IN THE SOCKET>\n\n");
printf ("The string recd <%s>",kb_buffer [r_id ]);
if ( strcmp ( kb_buffer[r_id] , "END ALL CONNECTION"))
printf ("Ending this connection \n") ;
else {
printf ("\n--> ENDING ALL CONNECTIONS" ) ;
exit (1) ;
}
/* reset the buffer */
kbstatus [r_id++] = 0 ;
}
sleep (5) ;
} while ( 1 ) ;
}
----====END OF SOURCE
--kannan
Concurrent Engineering Research Center,
West Virginia University, Morgantown.
More information about the Comp.lang.c
mailing list