pollシステムコールを使ったTCPサーバ
戻る
あまりよろしい例ではありません。
かなり強引な実装です(^^;
::::::::::::::
Makefile
::::::::::::::
# $Id: Poll-test.html,v 1.1 2009/06/22 16:11:52 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: Poll-test.html,v 1.1 2009/06/22 16:11:52 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;
}
::::::::::::::
Poll-test.c
::::::::::::::
#include <sys/poll.h>
#include <stdio.h>
int main() {
struct pollfd fds[ 3 ];
int ifd1, ifd2, ofd, count;
fds[ 0 ].fd = ifd1;
fds[ 0 ].events = POLLIN;
fds[ 1 ].fd = ifd2;
fds[ 1 ].events = POLLIN;
fds[ 2 ].fd = ofd;
fds[ 2 ].events = POLLOUT;
count = poll( fds, 3, 10000 );
if ( count == -1 ) {
perror( "poll failed" );
exit( 1 );
}
if ( count == 0 )
printf( "No data for reading or writing\n" );
if ( fds[ 0 ].revents & POLLIN )
printf( "There is data for reading fd %d\n", fds[ 0 ].fd );
if ( fds[ 1 ].revents & POLLIN )
printf( "There is data for reading fd %d\n", fds[ 1 ].fd );
if ( fds[ 2 ].revents & POLLOUT )
printf( "There is room to write on fd %d\n", fds[ 2 ].fd );
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>
#include <poll.h>
#include <errno.h>
/**
* $Id: Poll-test.html,v 1.1 2009/06/22 16:11:52 kishi Exp kishi $
*/
int main( int argc, char** argv ) {
const int OPEN_MAX = 5;
int i, maxi;
struct pollfd client_fds[ 10 ];
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
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" );
client_fds[ 0 ].fd = server_sockfd;
client_fds[ 0 ].events = POLLIN;
for ( i = 1;i < OPEN_MAX;i++ ) {
client_fds[ i ].fd = -1;
}
maxi = 0;
/** wait for client's requests */
while ( 1 ) {
char ch;
int fd;
int nready;
nready = poll( client_fds, maxi + 1, 100 /** timeout */ );
printf( "nready=%d\n", nready );
if ( client_fds[ 0 ].revents & POLLIN ) {
client_len = sizeof( client_address );
client_sockfd = accept( server_sockfd, ( struct sockaddr* ) & client_address, &client_len );
for ( i = 1;i < OPEN_MAX;i++ ) {
if ( client_fds[ i ].fd < 0 ) {
client_fds[ i ].fd = client_sockfd;
break;
}
}
if ( i == OPEN_MAX ) {
perror( "too much clients!" );
continue;
}
client_fds[ i ].events = POLLIN;
if ( i > maxi ) {
maxi = i;
}
if ( -nready <= 0 ) {
continue;
}
}
int n;
for ( i = 1;i <= maxi;i++ ) {
if ( ( fd = client_fds[ i ].fd ) < 0 ) {
continue;
}
if ( client_fds[ i ].revents & ( POLLIN | POLLERR ) ) {
if ( ( n = read( fd, &ch, 1 ) ) < 0 ) {
if ( errno == ECONNRESET ) {
// in case when client resets connection
close( fd );
client_fds[ i ].fd = -1;
} else {
perror( "read error!" );
}
} else if ( n == 0 ) {
// in case when client closes connection
close( fd );
client_fds[ i ].fd = -1;
} else {
ch++;
write( fd, &ch, 1 );
}
if ( -nready <= 0 ) {
continue;
}
}
}
}
return 0;
}
::::::::::::::
requestor.sh
::::::::::::::
#/bin/sh
PORT=11111
for index in `seq 1 100`; do
./Client ${PORT} &
done
戻る