selectシステムコールを使ったTCPサーバ
::::::::::::::
Makefile
::::::::::::::
# $Id: select.html,v 1.1 2009/06/22 16:12:25 kishi Exp kishi $
# @author KISHI Yasuhiro
CFLAGS = -c -Wall -O2
OBJECT1 = Server.o
EXE1 = Server.exe
OBJECT2 = Client.o
EXE2 = Client.exe
all: Server Client
Server: $(OBJECT1)
gcc $(OBJECT1) -o $(EXE1) && strip $(EXE1)
Server.o: Server.c
gcc $(CFLAGS) Server.c
Client: $(OBJECT2)
gcc $(OBJECT2) -o $(EXE2) && strip $(EXE2)
Client.o: Client.c
gcc $(CFLAGS) Client.c
clean:
rm -f *.o *.exe *~ *.bak *.orig
indent:
astyle -c -a -P *.c
::::::::::::::
Client.c
::::::::::::::
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <sys/un.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
/** $Id: select.html,v 1.1 2009/06/22 16:12:25 kishi Exp kishi $ */
int main( int argc, char** argv ) {
int sockfd;
int len;
struct sockaddr_in address;
int result;
char ch = 'X';
int portNumber;
if ( argc != 2 ) {
fprintf( stderr, "Usage: %s [portNumber]\n", argv[ 0 ] );
return 1;
}
portNumber = atoi( argv[ 1 ] );
sockfd = socket( AF_INET, SOCK_STREAM, 0 );
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr( "127.0.0.1" );
//-----------------------------------------------------------------
// htonl() is usually used, but this is cygwin's case
//-----------------------------------------------------------------
address.sin_port = htons ( portNumber );
len = sizeof( address );
result = connect( sockfd, ( struct sockaddr* ) & address, len );
if ( result == - 1 ) {
perror( "oops: cannot connect\n" );
return - 1;
}
write( sockfd, &ch, 1 );
read( sockfd, &ch, 1 );
printf( "response from server: %c\n", ch );
close( sockfd );
return 0;
}
::::::::::::::
Server.c
::::::::::::::
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdlib.h>
/**
* $Id: select.html,v 1.1 2009/06/22 16:12:25 kishi Exp kishi $
*/
int main( int argc, char** argv ) {
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
int result;
fd_set readfds, testfds;
int portNumber;
if ( argc != 2 ) {
fprintf( stderr, "Usage: %s [portNumber]\n", argv[ 0 ] );
return 1;
}
portNumber = atoi( argv[ 1 ] );
/** create server socket */
bzero ( ( char * ) & server_address, sizeof ( server_address ) );
server_sockfd = socket( AF_INET, SOCK_STREAM, 0 );
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl( INADDR_ANY );
//-----------------------------------------------------------------
// htonl() is usually used, but this is cygwin's case
//-----------------------------------------------------------------
server_address.sin_port = htons( portNumber );
server_len = sizeof( server_address );
bind( server_sockfd, ( struct sockaddr * ) & server_address, server_len );
printf( "bind...\n" );
/** create connection queue and initialize */
listen( server_sockfd, 10 );
printf( "listen...\n" );
FD_ZERO( &readfds );
FD_SET( server_sockfd, &readfds );
/** wait for client's requests */
while ( 1 ) {
char ch;
int fd;
int nread;
testfds = readfds;
printf( "Server is waiting...\n" );
result = select( FD_SETSIZE, &testfds, ( fd_set* ) 0, ( fd_set* ) 0, ( struct timeval * ) 0 );
if ( result < 1 ) {
perror( "Error!" );
}
for ( fd = 0;fd < FD_SETSIZE;fd++ ) {
if ( FD_ISSET( fd, &testfds ) ) {
if ( fd == server_sockfd ) {
client_sockfd = accept( server_sockfd, ( struct sockaddr* ) & client_address, &client_len );
FD_SET( client_sockfd, &readfds );
printf( "-- adding client on fd %d\n", client_sockfd );
} else {
ioctl( fd, FIONREAD, &nread );
if ( nread == 0 ) {
close( fd );
FD_CLR( fd, &readfds );
printf( "-- removing client on fd %d\n", fd );
} else {
read( fd, &ch, 1 );
printf( "Client's request: %c\n", ch );
//
// emulates doing something at server side
//
sleep( 1 );
ch++;
write( fd, &ch, 1 );
}
}
}
}
}
return 0;
}
::::::::::::::
requestor.sh
::::::::::::::
#/bin/sh
PORT=11111
./Server ${PORT} &
sleep 5
for index in `seq 1 50`; do
./Client ${PORT} &
done