Linux网络编程--聊天室客户端程序

Linux网络编程-聊天室客户端程序

#define _GNU_SOURCE 1
#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 <string.h>
#include <stdlib.h>
#include <poll.h>
#include <fcntl.h>

#define BUFFER_SIZE 64

int main( int argc, char* argv[] )
{
    if( argc <= 2 )
    {
        printf( "usage: %s ip_address port_number\n", 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 sockfd = socket( PF_INET, SOCK_STREAM, 0 );
    assert( sockfd >= 0 );
    if ( connect( sockfd, ( struct sockaddr* )&server_address, sizeof( server_address ) ) < 0 )
    {
        printf( "connection failed\n" );
        close( sockfd );
        return 1;
    }

    struct pollfd fds[2];
    fds[0].fd = 0;
    fds[0].events = POLLIN;
    fds[0].revents = 0;
    fds[1].fd = sockfd;
    fds[1].events = POLLIN | POLLRDHUP;
    fds[1].revents = 0;
    char read_buf[BUFFER_SIZE];
    int pipefd[2];
    int ret = pipe( pipefd );
    assert( ret != -1 );

    while( 1 )
    {
        ret = poll( fds, 2, -1 );
        if( ret < 0 )
        {
            printf( "poll failure\n" );
            break;
        }

        if( fds[1].revents & POLLRDHUP )
        {
            printf( "server close the connection\n" );
            break;
        }
        else if( fds[1].revents & POLLIN )
        {
            memset( read_buf, '\0', BUFFER_SIZE );
            recv( fds[1].fd, read_buf, BUFFER_SIZE-1, 0 );
            printf( "%s\n", read_buf );
        }

        if( fds[0].revents & POLLIN )
        {
            ret = splice( 0, NULL, pipefd[1], NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
            ret = splice( pipefd[0], NULL, sockfd, NULL, 32768, SPLICE_F_MORE | SPLICE_F_MOVE );
        }
    }
   
    close( sockfd );
    return 0;
}

测试1
开启服务端侦听:nc -l  6789
运行客户端程序:./a.out  127.0.0.1  6789

[fes@fes ~]$ nc -l 6789
Hello World
Hi Boy
hi gils

[fes@fes test]$ ./a.out 127.0.0.1 6789
Hello World
Hi Boy
hi gils

测试2

[fes@fes test]$ ./a.out 202.108.22.5 80
GET / HTTP/1.0

 

HTTP/1.1 200 OK
Date: Tue, 28 Oct 2014 08:42:21 GMT
Content-Type: text/html
Content-Length: 14613
Last-Modified: Wed, 03 Sep 2014 02:48:32 GMT
Connection: Close
Vary: Accept-Encoding
Set-Cookie: BAIDUID=BB394409C2863298A47B3D23F81817CC:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BAIDUPSID=BB394409C2863298A47B3D23F81817CC; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=0; path=/
P3P: CP=" OTI DSP COR IVA OUR IND COM "
Server: BWS/1.1
Pragma: no-cache
Cache-control: no-cache
BDPAGETYPE: 1
BDQID: 0xac1b0f5500017ba2
BDUSERID: 0
Accept-Ranges: bytes

<!DOCTYPE html><!--STATUS OK-->
<html>
<head>
 <meta http-equiv="content-type" content="text/html;charset=utf-8">
 <meta http-equiv="X-UA-Compatible" content="IE=Edge">
 <link rel="dns-prefetch" href="//s1.bdstatic.com"/>
 <link rel="dns-prefetch" href="//t1.baidu.com"/>
 <link rel="dns-prefetch" href="//t2.baidu.com"/>
 <link rel="dns-prefetch" href="//t3.baidu.com"/>
 <link rel="dns-prefetch" href="//t10.baidu.com"/>
 <link rel="dns-prefetch" href="//t11.baidu.com"/>
 <link rel="dns-prefetch" href="//t12.baidu.com"/>
 <link rel="dns-prefetch" href="//b1.bdstatic.com"/>

......

客户端连接百度,实现HTTP测试
程序收获
1、poll函数在IO复用中的应用
2、splice函数高效复制
3、nc命令在网络中的应用