//assignment #4
//compile: cc sockets_server.c -lxnet
#include < stdio.h >
/* ipc stuff */
#include < sys/types.h >
#include < sys/socket.h >
#include < netinet/in.h >
#include < arpa/inet.h >
/* semaphore & shared memory stuff */
#include < sys/ipc.h >
#include < sys/shm.h >
#include < sys/sem.h >
#include < fcntl.h>
/* signal stuff */
#include < signal.h >
/* ipc stuff */
#define PORTNUM 6779
/* semaphore & shared memory stuff */
#define SEM_MODE ( 0200 | 0400 | IPC_CREAT)
#define NUM_OF_SEM 1
void pOperation( void ) ;
void vOperation( void ) ;
void cleanUp() ;
struct sembuf *ptrsembuf ;
union semun
{
int val ;
struct semid_ds *buf ;
ushort *array ;
};
typedef struct
{
int i ;
char buffer[ 8 ] ;
} SharedMemory ;
int semid ;
int shmid ;
/* main */
int main()
{
/* ipc stuff */
int clilen, childpid, length ;
register int i,
TheSocket,
TheSocketConnection,
StructureLength ;
struct sockaddr_in ServerUnixSocketAddress,
ClientUnixSocketAddress ;
/* semaphore & shared memory stuff */
SharedMemory *sMemory ;
int semnum = 0 ;
int semval ;
union semun initvar ;
initvar.val = 1 ;
/* get semphore */
if( ( semid = semget( IPC_PRIVATE, NUM_OF_SEM, SEM_MODE ) ) == -1 )
{
perror( "semget" ) ;
exit( -1 ) ;
}
/* init count to 1 */
if( semctl( semid, semnum, SETVAL, initvar ) == -1 )
{
perror( "semctl" ) ;
exit( -1 ) ;
}
/* check count is = to 1 */
if( ( semval = semctl( semid, semnum, GETVAL, initvar ) ) == -1 )
{
perror( "semctl getval" ) ;
exit( -1 ) ;
}
printf( "semaphore value is = %d\n", semval ) ;
/* attempt to attach to an existing memory segment
// the size of SharedMemory structure
*/
if( ( shmid = shmget( IPC_PRIVATE, sizeof( SharedMemory ), IPC_CREAT | 0666 ) ) < 0 )
{
perror( "shmid" ) ;
exit( 1 ) ;
}
/* attach the shared memory segment
// get address of sMemory
*/
sMemory =(SharedMemory*)shmat( shmid,NULL,0 ) ;
if( sMemory ==(SharedMemory *) -1 )
{
perror( "shmat" ) ;
exit( 1 );
}
/* init semaphores */
ptrsembuf = (struct sembuf*)malloc( sizeof( struct sembuf ) ) ;
ptrsembuf->sem_op = 1 ;
ptrsembuf->sem_num = 0 ;
ptrsembuf->sem_flg = 0 ;
/* ipc stuff */
TheSocket = socket( AF_INET, SOCK_STREAM, 0 ) ;
if( TheSocket < 0 )
{
perror( "server error: socket() failed" ) ;
cleanUp() ;
exit( -1 ) ;
}
bzero( ( char * ) &ServerUnixSocketAddress,
sizeof( ServerUnixSocketAddress ) ) ;
ServerUnixSocketAddress.sin_family = AF_INET ;
ServerUnixSocketAddress.sin_addr.s_addr = htonl( INADDR_ANY ) ;
ServerUnixSocketAddress.sin_port = htons( PORTNUM ) ;
unlink( TheSocket ) ;
if( bind( TheSocket,
(struct sockaddr *)&ServerUnixSocketAddress,
sizeof( ServerUnixSocketAddress ) ) < 0 )
{
perror( "server error: connect() failed" ) ;
cleanUp() ;
exit( -1 ) ;
}
if( listen( TheSocket, 5 ) < 0 )
{
perror( "server error: listen() failed" ) ;
cleanUp() ;
exit( -1 ) ;
}
/* set up signal */
signal(SIGINT, cleanUp) ;
/* the loop */
sMemory->i = 0 ;
do
{
clilen = sizeof( ClientUnixSocketAddress ) ;
TheSocketConnection = accept( TheSocket,
(struct sockaddr *)&ClientUnixSocketAddress,
&clilen ) ;
if( TheSocketConnection < 0 )
{
perror( "server error: accept() failed" ) ;
cleanUp() ;
exit( -1 ) ;
}
childpid = fork() ;
if( childpid < 0 )
{
perror( "server error: fork() failed" ) ;
cleanUp() ;
exit( -1 ) ;
}
else if( childpid == 0 )
{
close( TheSocket ) ;
pOperation() ;
/* critical region */
read( TheSocketConnection,
sMemory->buffer,
length ) ;
sleep( 2 ) ;
write( TheSocketConnection,
sMemory->buffer,
length ) ;
/* end critical region */
vOperation() ;
/* close child process */
exit( 0 ) ;
}
close( TheSocketConnection ) ;
} while( 1 ) ;
}
/* clean up shared memory && semaphores */
void cleanUp( void )
{
/* remove shared memory */
if( shmctl( shmid, IPC_RMID, 0 ) == -1 )
{
perror( "shmctl" ) ;
exit( -1 ) ;
}
else
printf( "\nshared memory successfully deleted....\n" ) ;
/* remove semaphore */
if( semctl( semid, NUM_OF_SEM, IPC_RMID ) == -1 )
{
perror( "semctl" ) ;
exit( -1 ) ;
}
else
printf( "semaphore successfully deleted....\n" ) ;
printf( "***********finished serving**************\n\n" ) ;
}
/* P operation */
void pOperation( void )
{
ptrsembuf->sem_op = -1 ;
if( semop( semid, ptrsembuf, 1 ) == -1 )
{
perror( "semop pOperation" ) ;
exit( -1 ) ;
}
}
/* V operation */
void vOperation( void )
{
ptrsembuf->sem_op = 1 ;
if( semop( semid, ptrsembuf, 1 ) == -1 )
{
perror( "semop vOperation" ) ;
exit( -1 ) ;
}
}