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


戻る

inserted by FC2 system