• linux socket编程示例


    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <signal.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <stdio.h>
    #include <string.h>
    
    static bool stop = false;
    static void handle_term( int sig ) // kill pid;  in another tty will triggle this signal
    {
        stop = true;
        printf("signal SIGTERM catched...
    ");
    }
    
    static void handle_int(int sig)  // ctrl+c; will triggle this signal
    {
        printf("signal SIGINT catched...
    ");
        stop = true;   
    }
    
    
    //./listen 127.0.0.1 8888 100
    
    int main( int argc, char* argv[] )
    {
        signal( SIGTERM, handle_term );
        signal(SIGINT, handle_int);
    
        if( argc <= 3 )
        {
            printf( "usage: %s ip_address port_number backlog
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
        int backlog = atoi( argv[3] );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        printf("after bind...
    ");
    
        //backlog is the max number of waitting connect in wait queue
        ret = listen( sock, backlog );   //listen is a none-block function
        assert( ret != -1 );
        printf("after listen...
    ");
    
        while ( ! stop )
        {
            sleep( 1 );
        }
    
        close( sock );
        return 0;
    }
    

      

     

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 2 )
        {
            printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int reuse = 1;
        setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
        printf("AFTER bind...
    ");
    
        ret = listen( sock, 5 );
        assert( ret != -1 );
        printf("AFTER listen...
    ");
        
        //the returned client is client's address
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof( client );
        int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); //accept is a block function
        printf("AFTER accept...
    ");
        
        if ( connfd < 0 )
        {
            printf( "errno is: %d
    ", errno );
        }
        else
        {
            //#define INET_ADDRSTRLEN 16 , IPV4 address char array length, <netinet/in.h>
            char remote[INET_ADDRSTRLEN ];
            printf( "connected with ip: %s and port: %d
    ", 
                inet_ntop( AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client.sin_port ) );
            close( connfd );
        }
    
        close( sock );
        return 0;
    }
    

      

     

     

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    
    #define BUF_SIZE 1024
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 2 )
        {
            printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        ret = listen( sock, 5 );
        assert( ret != -1 );
        printf("after listen...
    ");
    
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof( client );
        int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
        printf("after accept...
    ");
        if ( connfd < 0 )
        {
            printf( "errno is: %d
    ", errno );
        }
        else
        {
            char buffer[ BUF_SIZE ];
    
            memset( buffer, '', BUF_SIZE );
            ret = recv( connfd, buffer, BUF_SIZE-1, 0 );
            printf( "got %d bytes of normal data '%s'
    ", ret, buffer );
    
            memset( buffer, '', BUF_SIZE );
            //MSG_OOB: support recv out-of-band data
            //Only TCP support oob data
            //TCP only 1 byte oob data
            //use MSG_OOB flag when call send to send oob data
            ret = recv( connfd, buffer, BUF_SIZE-1, MSG_OOB ); 
            printf( "got %d bytes of oob data '%s'
    ", ret, buffer );
    
            memset( buffer, '', BUF_SIZE );
            ret = recv( connfd, buffer, BUF_SIZE-1, 0 );
            printf( "got %d bytes of normal data '%s'
    ", ret, buffer );
    
            close( connfd );
        }
    
        close( sock );
        return 0;
    }
    

     

    connect

     

    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define BUFFER_SIZE 512
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 3 )
        {
            printf( "usage: %s ip_address port_number send_bufer_size
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        struct sockaddr_in server_address;
        bzero( &server_address, sizeof( server_address ) );
        server_address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &server_address.sin_addr );
        server_address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int sendbuf = atoi( argv[3] );
        int len = sizeof( sendbuf );
        setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) );
        getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len );
        printf( "the tcp send buffer size after setting is %d
    ", sendbuf );
    
        if ( connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) ) != -1 )
        {
            //
            printf("call getsockname ...
    ");
            struct sockaddr_in local_address;
            socklen_t length;
            int ret = getpeername(sock, ( struct sockaddr* )&local_address, &length);
            assert(ret == 0);
            char local[INET_ADDRSTRLEN ];
            printf( "local with ip: %s and port: %d
    ",
                inet_ntop( AF_INET, &local_address.sin_addr, local, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) );
            //
    
            char buffer[ BUFFER_SIZE ];
            memset( buffer, 'a', BUFFER_SIZE );
            send( sock, buffer, BUFFER_SIZE, 0 );
        }
    
        close( sock );
        return 0;
    }
    

     

      

    accept:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 2 )
        {
            printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );  
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int reuse = 1;
        setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
        printf("AFTER bind...
    ");
    
        ret = listen( sock, 5 );
        assert( ret != -1 );
        printf("AFTER listen...
    ");
        
        //the returned client is client's address
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof( client );
        int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength ); //accept is a block function
        printf("AFTER accept...
    ");
        
        if ( connfd < 0 )
        {
            printf( "errno is: %d
    ", errno );
        }
        else
        {
            //#define INET_ADDRSTRLEN 16 , IPV4 address char array length, <netinet/in.h>
            char remote[INET_ADDRSTRLEN ];
            printf( "connected with ip: %s and port: %d
    ", 
                inet_ntop( AF_INET, &client.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( client.sin_port ) );
            
            //
            printf("call getsockname ...
    ");
            struct sockaddr_in local_address;
            socklen_t length;
            int ret = getsockname(connfd, ( struct sockaddr* )&local_address, &length);
            if (ret == 0)
            {
                char local[INET_ADDRSTRLEN ];
                printf( "local connfd ip: %s and port: %d
    ", inet_ntop( AF_INET, &local_address.sin_addr, local, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) );
            }
            else
                printf("getsockname on connfd fail...
    ");
    
            bzero( &local_address, sizeof( local_address ) );
            ret = getpeername(connfd, ( struct sockaddr* )&local_address, &length);
            if (ret == 0)
            {
                char local1[INET_ADDRSTRLEN ];
                printf( "remote ip: %s and port: %d
    ", inet_ntop( AF_INET, &local_address.sin_addr, local1, INET_ADDRSTRLEN ), ntohs( local_address.sin_port ) );
    
            }
            else
                printf("getpeername on connfd fail...
    ");
    
            close( connfd );
        }
    
        close( sock );
        return 0;
    }
    

      

    setsendbuffer:

    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define BUFFER_SIZE 512
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 3 )
        {
            printf( "usage: %s ip_address port_number send_bufer_size
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        struct sockaddr_in server_address;
        bzero( &server_address, sizeof( server_address ) );
        server_address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &server_address.sin_addr );
        server_address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int sendbuf = atoi( argv[3] );
        int len = sizeof( sendbuf );
        setsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof( sendbuf ) );
        getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, ( socklen_t* )&len );
        printf( "the tcp send buffer size after setting is %d
    ", sendbuf );
    
        if ( connect( sock, ( struct sockaddr* )&server_address, sizeof( server_address ) ) != -1 )
        {
            char buffer[ BUFFER_SIZE ];
            memset( buffer, 'a', BUFFER_SIZE );
            send( sock, buffer, BUFFER_SIZE, 0 );
        }
    
        close( sock );
        return 0;
    }
    

      

    setrecvbuffer:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    
    #define BUFFER_SIZE 1024
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 3 )
        {
            printf( "usage: %s ip_address port_number receive_buffer_size
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
        int recvbuf = atoi( argv[3] );
        printf("recvbuf is %d
    ", recvbuf); /////!!!
        int len = sizeof( recvbuf );
        printf("len is %d
    ", len); /////!!!
        setsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, sizeof( recvbuf ) );
        getsockopt( sock, SOL_SOCKET, SO_RCVBUF, &recvbuf, ( socklen_t* )&len );
        printf( "the receive buffer size after settting is %d
    ", recvbuf );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        ret = listen( sock, 5 );
        assert( ret != -1 );
    
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof( client );
        int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
        if ( connfd < 0 )
        {
            printf( "errno is: %d
    ", errno );
        }
        else
        {
            char buffer[ BUFFER_SIZE ];
            memset( buffer, '', BUFFER_SIZE );
            while( recv( connfd, buffer, BUFFER_SIZE-1, 0 ) > 0 )
            {
                printf("%s
    ", buffer);
            }
            close( connfd );
        }
    
        close( sock );
        return 0;
    }
    

      

    daytime:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <assert.h>
    #include <errno.h>
    
    int main( int argc, char *argv[] )
    {
    	//assert( argc == 2 );
    	//char *host = argv[1];
    
    	struct hostent *host;   //存放主机信息
    	//char addr_p[NET_ADDR_STR_LEN]; //用于存放点分十进制IP地址的字符串
        if((host = gethostent()) == NULL)
        {
            perror("fail to get host's information
    ");
            return -1;
        }
        printf("hostName: %s
    " , host->h_name);
    
    	//用域名或主机名获取IP地址
    	struct hostent* hostinfo = gethostbyname( host->h_name );
    	assert( hostinfo );
    	struct servent* servinfo = getservbyname( "daytime", "tcp" );
    	assert( servinfo );
    	printf( "daytime port is %d
    ", ntohs( servinfo->s_port ) );
    
    	struct sockaddr_in address;
    	address.sin_family = AF_INET;
    	address.sin_port = servinfo->s_port;
    	address.sin_addr = *( struct in_addr* )*hostinfo->h_addr_list;
    
    	char remote[INET_ADDRSTRLEN ];
    	printf( "connected with ip: %s and port: %d
    ", 
                inet_ntop( AF_INET, &address.sin_addr, remote, INET_ADDRSTRLEN ), ntohs( address.sin_port ) );
    
    	int sockfd = socket( AF_INET, SOCK_STREAM, 0 );
    	//int reuse = 1;
        //setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
    	int result = connect( sockfd, (struct sockaddr* )&address, sizeof( address ) );
    	printf( "errno is: %d
    ", errno );
    	perror("connect error:");
    	assert( result != -1 );
    
    	char buffer[128];
    	result = read( sockfd, buffer, sizeof( buffer ) );
    	assert( result > 0 );
    	buffer[ result ] = '';
    	printf( "the day tiem is: %s", buffer );
    	close( sockfd );
        return 0;
    }
    

      

    testdup:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 2 )
        {
            printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        ret = listen( sock, 5 );
        assert( ret != -1 );
    
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof( client );
        int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
        if ( connfd < 0 )
        {
            printf( "errno is: %d
    ", errno );
        }
        else
        {
            close( STDOUT_FILENO );
            dup( connfd );
            printf( "abcd
    " ); //the same as write/send data in connfd
            close( connfd );
        }
    
        close( sock );
        return 0;
    }
    

      

    writev:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <fcntl.h>
    
    #define BUFFER_SIZE 1024
    static const char* status_line[2] = { "200 OK", "500 Internal server error" };
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 3 )
        {
            printf( "usage: %s ip_address port_number filename
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
        const char* file_name = argv[3];
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        ret = listen( sock, 5 );
        assert( ret != -1 );
    
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof( client );
        int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
        if ( connfd < 0 )
        {
            printf( "errno is: %d
    ", errno );
        }
        else
        {
            char header_buf[ BUFFER_SIZE ];
            memset( header_buf, '', BUFFER_SIZE );
            char* file_buf;
            struct stat file_stat;
            bool valid = true;
            int len = 0;
            if( stat( file_name, &file_stat ) < 0 )
            {
                valid = false;
            }
            else
            {
                if( S_ISDIR( file_stat.st_mode ) )
                {
                    valid = false;
                }
                else if( file_stat.st_mode & S_IROTH )
                {
                    int fd = open( file_name, O_RDONLY );
                    file_buf = new char[ file_stat.st_size + 1 ];
                    memset( file_buf, '', file_stat.st_size + 1 );
                    if ( read( fd, file_buf, file_stat.st_size ) < 0 )
                    {
                        valid = false;
                    }
                }
                else
                {
                    valid = false;
                }
            }
            
            if( valid )
            {
                ret = snprintf( header_buf, BUFFER_SIZE-1, "%s %s
    ", "HTTP/1.1", status_line[0] );
                len += ret;
                ret = snprintf( header_buf + len, BUFFER_SIZE-1-len, 
                                 "Content-Length: %d
    ", (int)file_stat.st_size );
                len += ret;
                ret = snprintf( header_buf + len, BUFFER_SIZE-1-len, "%s", "
    " );
                struct iovec iv[2];
                iv[ 0 ].iov_base = header_buf;
                iv[ 0 ].iov_len = strlen( header_buf );
                iv[ 1 ].iov_base = file_buf;
                iv[ 1 ].iov_len = file_stat.st_size;
                ret = writev( connfd, iv, 2 );
            }
            else
            {
                ret = snprintf( header_buf, BUFFER_SIZE-1, "%s %s
    ", "HTTP/1.1", status_line[1] );
                len += ret;
                ret = snprintf( header_buf + len, BUFFER_SIZE-1-len, "%s", "
    " );
                send( connfd, header_buf, strlen( header_buf ), 0 );
            }
            close( connfd );
            delete [] file_buf;
        }
    
        close( sock );
        return 0;
    }
    

      

     sendfile:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/sendfile.h>
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 3 )
        {
            printf( "usage: %s ip_address port_number filename
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
        const char* file_name = argv[3];
    
        int filefd = open( file_name, O_RDONLY );
        assert( filefd > 0 );
        struct stat stat_buf;
        fstat( filefd, &stat_buf );
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        ret = listen( sock, 5 );
        assert( ret != -1 );
    
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof( client );
        int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
        if ( connfd < 0 )
        {
            printf( "errno is: %d
    ", errno );
        }
        else
        {
            //linux, not GNU. high performance send a file, 'zero copy'
            sendfile( connfd, filefd, NULL, stat_buf.st_size );
            close( connfd );
        }
    
        close( sock );
        return 0;
    }
    

      

     splice:

    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 2 )
        {
            printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int sock = socket( PF_INET, SOCK_STREAM, 0 );
        assert( sock >= 0 );
    
        int ret = bind( sock, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        ret = listen( sock, 5 );
        assert( ret != -1 );
    
        struct sockaddr_in client;
        socklen_t client_addrlength = sizeof( client );
        int connfd = accept( sock, ( struct sockaddr* )&client, &client_addrlength );
        if ( connfd < 0 )
        {
            printf( "errno is: %d
    ", errno );
        }
        else
        {
            int pipefd[2];
            assert( ret != -1 );
            ret = pipe( pipefd ); //pipe, pipefd[0] is opened for read, pipefd[1] is opened for write. 
            //splice用于在两个文件描述符之间移动数据, 也是零拷贝。使用splice时, fd_in和fd_out中必须至少有一个是管道文件描述符。
            //sendfile只适用于将数据从文件拷贝到套接字上,限定了它的使用范围。Linux在2.6.17版本引入splice系统调用,
            //用于在两个文件描述符中移动数据.
    
            //an ECHO implement use splice.
            //copy data from connfd(recv from client) to pipefd[1]
            ret = splice( connfd, NULL, pipefd[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE ); 
            assert( ret != -1 );
            //copy data from pipefd[1] -->pipefd[0] --> connfd, send to client.
            ret = splice( pipefd[0], NULL, connfd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
            assert( ret != -1 );
            close( connfd );
        }
    
        close( sock );
        return 0;
    }
    

      

    tee:

    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    
    int main( int argc, char* argv[] )
    {
    	if ( argc != 2 )
    	{
    		printf( "usage: %s <file>
    ", argv[0] );
    		return 1;
    	}
    	int filefd = open( argv[1], O_CREAT | O_WRONLY | O_TRUNC, 0666 );
    	assert( filefd > 0 );
    
    	int pipefd_stdout[2];
        int ret = pipe( pipefd_stdout );
    	assert( ret != -1 );
    
    	int pipefd_file[2];
        ret = pipe( pipefd_file );
    	assert( ret != -1 );
    
    	//close( STDIN_FILENO );
    	// dup2( pipefd_stdout[1], STDIN_FILENO );
    	//write( pipefd_stdout[1], "abc
    ", 4 );
    
    	//copy data: stdin --> pipefd_stdout[1]
    	ret = splice( STDIN_FILENO, NULL, pipefd_stdout[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
    	assert( ret != -1 );
    
    	//tee在两个管道文件描述符之间复制数据,同是零拷贝。但它不消耗数据,数据被操作之后,仍然可以用于后续操作。 
    	//copy data: pipefd_stdout[0] --> pipefd_file[1]
    	ret = tee( pipefd_stdout[0], pipefd_file[1], 32768, SPLICE_F_NONBLOCK ); 
    	assert( ret != -1 );
    
    	//copy data: pipefd_file[0] --> filefd
    	ret = splice( pipefd_file[0], NULL, filefd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
    	assert( ret != -1 );
    
    	//copy data: pipefd_stdout[0] --> stdout
    	ret = splice( pipefd_stdout[0], NULL, STDOUT_FILENO, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
    	assert( ret != -1 );
    
    	close( filefd );
        close( pipefd_stdout[0] );
        close( pipefd_stdout[1] );
        close( pipefd_file[0] );
        close( pipefd_file[1] );
    	return 0;
    }
    

      

     select:

     

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <stdlib.h>
    
    int main( int argc, char* argv[] )
    {
    	if( argc <= 2 )
    	{
    		printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
    		return 1;
    	}
    	const char* ip = argv[1];
    	int port = atoi( argv[2] );
    	printf( "ip is %s and port is %d
    ", ip, port );
    
    	int ret = 0;
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
    	int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
    	assert( listenfd >= 0 );
    
        ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
    	assert( ret != -1 );
    
    	ret = listen( listenfd, 5 );
    	assert( ret != -1 );
    
    	struct sockaddr_in client_address;
        socklen_t client_addrlength = sizeof( client_address );
    	int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
    	if ( connfd < 0 )
    	{
    		printf( "errno is: %d
    ", errno );
    		close( listenfd );
    	}
    
    	char remote_addr[INET_ADDRSTRLEN];
    	printf( "connected with ip: %s and port: %d
    ", inet_ntop( AF_INET, &client_address.sin_addr, remote_addr, INET_ADDRSTRLEN ), ntohs( client_address.sin_port ) );
    
    	char buf[1024];
        fd_set read_fds;
        fd_set exception_fds;
    
        FD_ZERO( &read_fds );
        FD_ZERO( &exception_fds );
    
        // option:SO_OOBINLINE, value:1 --- put out of band data into normal data.
        int nReuseAddr = 1;
    	setsockopt( connfd, SOL_SOCKET, SO_OOBINLINE, &nReuseAddr, sizeof( nReuseAddr ) );
    	while( 1 )
    	{
    		memset( buf, '', sizeof( buf ) );
    		FD_SET( connfd, &read_fds );
    		FD_SET( connfd, &exception_fds );
    
            ret = select( connfd + 1, &read_fds, NULL, &exception_fds, NULL );
    		printf( "select one
    " );
            if ( ret < 0 )
            {
            	printf( "selection failure
    " );
            	break;
            }
    	
            if ( FD_ISSET( connfd, &read_fds ) )
    		{
            	ret = recv( connfd, buf, sizeof( buf )-1, 0 );
    			if( ret <= 0 )
    			{
    				break;
    			}
    			printf( "get %d bytes of normal data: %s
    ", ret, buf );
    		}
    		else if( FD_ISSET( connfd, &exception_fds ) )
            {
            	ret = recv( connfd, buf, sizeof( buf )-1, MSG_OOB );
    			if( ret <= 0 )
    			{
    				break;
    			}
    			printf( "get %d bytes of oob data: %s
    ", ret, buf );
            	}
    
    	}
    
    	close( connfd );
    	close( listenfd );
    	return 0;
    }
    

     

      

    epoll:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <sys/epoll.h>
    #include <pthread.h>
    
    #define MAX_EVENT_NUMBER 1024
    #define BUFFER_SIZE 10
    
    int setnonblocking( int fd )
    {
        int old_option = fcntl( fd, F_GETFL );
        int new_option = old_option | O_NONBLOCK;
        fcntl( fd, F_SETFL, new_option );
        return old_option;
    }
    
    void addfd( int epollfd, int fd, bool enable_et )
    {
        epoll_event event;
        event.data.fd = fd;
        event.events = EPOLLIN;  //表示对应的文件描述符可以读(包括对端SOCKET正常关闭)
        if( enable_et )
        {
            //EPOLLET: 将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
            event.events |= EPOLLET;
        }
        epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event ); //register to epoll
        setnonblocking( fd );
    }
    
    void lt( epoll_event* events, int number, int epollfd, int listenfd )
    {
        char buf[ BUFFER_SIZE ];
        for ( int i = 0; i < number; i++ )
        {
            int sockfd = events[i].data.fd;
            if ( sockfd == listenfd )
            {
                struct sockaddr_in client_address;
                socklen_t client_addrlength = sizeof( client_address );
                int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
                addfd( epollfd, connfd, false );
            }
            else if ( events[i].events & EPOLLIN )
            {
                printf( "event trigger once
    " );
                memset( buf, '', BUFFER_SIZE );
                int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
                if( ret <= 0 )
                {
                    close( sockfd );
                    continue;
                }
                printf( "get %d bytes of content: %s
    ", ret, buf );
            }
            else
            {
                printf( "something else happened 
    " );
            }
        }
    }
    
    void et( epoll_event* events, int number, int epollfd, int listenfd )
    {
        char buf[ BUFFER_SIZE ];
        for ( int i = 0; i < number; i++ )
        {
            int sockfd = events[i].data.fd;
            if ( sockfd == listenfd )
            {
                struct sockaddr_in client_address;
                socklen_t client_addrlength = sizeof( client_address );
                int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
                addfd( epollfd, connfd, true );
            }
            else if ( events[i].events & EPOLLIN )
            {
                printf( "event trigger once
    " );
                while( 1 )
                {
                    memset( buf, '', BUFFER_SIZE );
                    int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
                    if( ret < 0 )
                    {
                        if( ( errno == EAGAIN ) || ( errno == EWOULDBLOCK ) )
                        {
                            printf( "read later
    " );
                            break;
                        }
                        close( sockfd );
                        break;
                    }
                    else if( ret == 0 )
                    {
                        close( sockfd );
                    }
                    else
                    {
                        printf( "get %d bytes of content: %s
    ", ret, buf );
                    }
                }
            }
            else
            {
                printf( "something else happened 
    " );
            }
        }
    }
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 2 )
        {
            printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        int ret = 0;
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
        assert( listenfd >= 0 );
    
        ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        ret = listen( listenfd, 5 );
        assert( ret != -1 );
    
        epoll_event events[ MAX_EVENT_NUMBER ];
        int epollfd = epoll_create( 5 ); //tell epoll the listen number is 5
        assert( epollfd != -1 );
        addfd( epollfd, listenfd, true );
    
        while( 1 )
        {
            //参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,
            //这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间
            //该函数返回需要处理的事件数目,如返回0表示已超时。
            int ret = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );
            if ( ret < 0 )
            {
                printf( "epoll failure
    " );
                break;
            }
        
            lt( events, ret, epollfd, listenfd );
            //et( events, ret, epollfd, listenfd );
        }
    
        close( listenfd );
        return 0;
    }
    

      

     oneshot:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <assert.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <errno.h>
    #include <string.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <sys/epoll.h>
    #include <pthread.h>
    
    #define MAX_EVENT_NUMBER 1024
    #define BUFFER_SIZE 1024
    
    struct fds
    {
       int epollfd;
       int sockfd;
    };
    
    int setnonblocking( int fd )
    {
        int old_option = fcntl( fd, F_GETFL );
        int new_option = old_option | O_NONBLOCK;
        fcntl( fd, F_SETFL, new_option );
        return old_option;
    }
    
    void addfd( int epollfd, int fd, bool oneshot )
    {
        epoll_event event;
        event.data.fd = fd;
        //EPOLLIN表示对应的文件描述符可以读(包括对端SOCKET正常关闭);
        //EPOLLET将EPOLL设为边缘触发(Edge Triggered)模式,这是相对于水平触发(Level Triggered)来说的。
        event.events = EPOLLIN | EPOLLET; //
        if( oneshot )
        {
            //EPOLLONESHOT:只监听一次事件,当监听完这次事件之后,如果还需要继续监听这个socket的话,
            //需要再次把这个socket加入到EPOLL队列里
            event.events |= EPOLLONESHOT;
        }
        //EPOLL_CTL_ADD:注册新的fd到epfd中;
        epoll_ctl( epollfd, EPOLL_CTL_ADD, fd, &event );
        setnonblocking( fd );
    }
    
    void reset_oneshot( int epollfd, int fd )
    {
        epoll_event event;
        event.data.fd = fd;
        event.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
        //EPOLL_CTL_MOD:修改已经注册的fd的监听事件;
        epoll_ctl( epollfd, EPOLL_CTL_MOD, fd, &event );
    }
    
    void* worker( void* arg )
    {
        int sockfd = ( (fds*)arg )->sockfd;
        int epollfd = ( (fds*)arg )->epollfd;
        printf( "start new thread to receive data on fd: %d
    ", sockfd );
        char buf[ BUFFER_SIZE ];
        memset( buf, '', BUFFER_SIZE );
        while( 1 )
        {
            int ret = recv( sockfd, buf, BUFFER_SIZE-1, 0 );
            //ret=0 -- 这里表示对端的socket已正常关闭.
            if( ret == 0 )
            {
                close( sockfd );
                printf( "foreiner closed the connection
    " );
                break;
            }
            else if( ret < 0 )
            {
                //sockfd is NONBLOCK, EAGAIN -- no more data to read, so reset sockfd again
                if( errno == EAGAIN )
                {
                    reset_oneshot( epollfd, sockfd );
                    printf( "read later
    " );
                    break;
                }
            }
            else
            {
                printf( "get content: %s
    ", buf );
                sleep( 5 );
            }
        }
        printf( "end thread receiving data on fd: %d
    ", sockfd );
    }
    
    int main( int argc, char* argv[] )
    {
        if( argc <= 2 )
        {
            printf( "usage: %s ip_address port_number
    ", basename( argv[0] ) );
            return 1;
        }
        const char* ip = argv[1];
        int port = atoi( argv[2] );
    
        int ret = 0;
        struct sockaddr_in address;
        bzero( &address, sizeof( address ) );
        address.sin_family = AF_INET;
        inet_pton( AF_INET, ip, &address.sin_addr );
        address.sin_port = htons( port );
    
        int listenfd = socket( PF_INET, SOCK_STREAM, 0 );
        assert( listenfd >= 0 );
    
        ret = bind( listenfd, ( struct sockaddr* )&address, sizeof( address ) );
        assert( ret != -1 );
    
        ret = listen( listenfd, 5 );
        assert( ret != -1 );
    
        epoll_event events[ MAX_EVENT_NUMBER ];
        int epollfd = epoll_create( 5 );
        assert( epollfd != -1 );
        addfd( epollfd, listenfd, false );
    
        while( 1 )
        {
            int ret = epoll_wait( epollfd, events, MAX_EVENT_NUMBER, -1 );
            if ( ret < 0 )
            {
                printf( "epoll failure
    " );
                break;
            }
        
            for ( int i = 0; i < ret; i++ )
            {
                int sockfd = events[i].data.fd;
                if ( sockfd == listenfd )
                {
                    struct sockaddr_in client_address;
                    socklen_t client_addrlength = sizeof( client_address );
                    int connfd = accept( listenfd, ( struct sockaddr* )&client_address, &client_addrlength );
                    addfd( epollfd, connfd, true );
                }
                else if ( events[i].events & EPOLLIN )
                {
                    pthread_t thread;
                    fds fds_for_new_worker;
                    fds_for_new_worker.epollfd = epollfd;
                    fds_for_new_worker.sockfd = sockfd;
                    pthread_create( &thread, NULL, worker, ( void* )&fds_for_new_worker );
                }
                else
                {
                    printf( "something else happened 
    " );
                }
            }
        }
    
        close( listenfd );
        return 0;
    }
    

      

     

     

  • 相关阅读:
    HDU 1104 Remainder (POJ 2426 BFS+数论)
    POJ 1398 Complete the sequence! ★ (差分)
    POJ 2917 Diophantus of Alexandria ★(数论)
    POJ 1948 Triangular Pastures (二维01背包)
    POJ 1948 Triangular Pastures (二维01背包)
    starter kits 介绍
    starter kits 介绍
    信息分析与预测复习题(绪论)
    信息分析与预测复习题(绪论)
    starter kits 介绍
  • 原文地址:https://www.cnblogs.com/kex1n/p/7414181.html
Copyright © 2020-2023  润新知