zoukankan      html  css  js  c++  java
  • linux网络编程初探

     1.单客户端模式的程序       来源:《Linux程序设计》第4版 15.2节

    /*----头文件与变量声明-----------------------------------------------------*/
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main()
    {
        int sockfd;
        int len;
        struct sockaddr_in address;
        int result;
        char ch = 'A';
    
    /*--为客户建立一个套接字----------------------------------------------------*/
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    /*--根据服务器的情况给套接字命名----------------------------------------------*/
        address.sin_family = AF_INET;
        address.sin_addr.s_addr = inet_addr("127.0.0.1");
        address.sin_port = htons(9734);
        len = sizeof(address);
    
    /*--将我们的套接字连接到服务器的套接字------------------------------------------*/
        result = connect(sockfd, (struct sockaddr *)&address, len);
        if(result == -1){
            perror("oops: connection failed");
            exit(1);
        }
    
    /*--现在就可以通过sockfd进行读写操作了-----------------------------------------*/
        write(sockfd, &ch, 1);
        read(sockfd, &ch, 1);
        printf("char from server = %c
    ", ch);
        close(sockfd);
        exit(0);
    }
    client.c
    /*-头文件与变量声明--------------------------------------------------------*/
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdlib.h>
    
    int main()
    {
        int server_sockfd, client_sockfd;
        int server_len, client_len;
        struct sockaddr_in server_address;
        struct sockaddr_in client_address;
    
    /*--删除以前的套接字,为服务器创建一个未命名的套接字-------------------------*/
        unlink("server_socket");
        server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    
    /*------命名套接字-----------------------------------------------------------*/
        server_address.sin_family = AF_INET;
        server_address.sin_addr.s_addr = htonl(INADDR_ANY);
        server_address.sin_port = htons(9734);
        server_len = sizeof(server_address);
        bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
    
    /*---创建一个连接队列,开始等待客户进行连接----------------------------------*/
        listen(server_sockfd, 5);
        while(1){
            char ch;
    
            printf("server waiting
    ");
    
    /*------接受一个连接---------------------------------------------------------*/
            client_len = sizeof(client_address);
            client_sockfd = accept(server_sockfd,
                (struct sockaddr *)&client_address, &client_len);
    
    /*----对client_sockfd套接字上的客户进行读写操作------------------------------*/
            read(client_sockfd, &ch, 1);
            ch++;
            write(client_sockfd, &ch, 1);
            close(client_sockfd);
        }
    }
    server.c

     0基础者请将程序拷出,对照下面注释查看

    2.编写套接字通信程序的步骤

    ①socket:创建套接字
    -------------------------------------------------------------------------------------
    #include <sys/types.h>
    #include <sys/socket.h>
    int socket(  int domain,
          int type,
          int protocol);

    domain(套接字域)取值:
    AF_UNIX:unix文件系统套接字
    AF_INET:因特网套接字

    type(套接字类型)取值:
    SOCK_STREAM:TCP流套接字
    SOCK_DGRAM:UDP数据报套接字

    protocol取值:
    0(默认协议)

     

    ②sockaddr_in/sockaddr_un:套接字初始化
    -------------------------------------------------------------------------------------
    #include <sys/un.h>
    struct sockaddr_un {
    sa_family_t  sun_family;  /*AF_UNIX*/
    char       sun_path[]; /*pathname*/
    }

    ---------------------------------
    #include <netinet/in.h>
    struct sockaddr_in {
    short int         sin_family; /*AF_INET*/
    unsigned short int  sin_port;   /*Port number*/
    struct in_addr    sin_addr;   /*Internet address*/
    }
    其中IP地址结构in_addr被定义为:
    struct in_addr {
    unsigned long int s_addr;
    };

     

    ③bind:命名套接字
    -------------------------------------------------------------------------------------
    #include <sys/socket.h>
    int bind( int socket,
         const struct sockaddr *address,
         size_t address_len);

     

    ④listen:服务器创建套接字队列
    -------------------------------------------------------------------------------------
    #include <sys/socket.h>
    int listen(int socket, int backlog)

    backlog表示队列长度,队列中未处理连接数大于backlog值时,拒绝连接
    listen函数成功时返回0,失败时返回-1

     

    ⑤accept:服务器接受连接
    -------------------------------------------------------------------------------------
    #include <sys/socket.h>
    int accept(  int socket,
          struct sockaddr *address,
          size_t *address_len);

    accept系统调用只有当有客户试图连接到由socket参数指定的套接字上时才返回。
    accept函数将创建一个新套接字来与该客户进行通信,并返回新套接字的描述符。
    当有未处理客户连接时,accept函数将返回一个新的套接字文件描述符。
    当发生错误时, accept函数返回-1


    若套接字队列中无未处理连接,accept将其阻塞(程序将暂停)直到有客户建立连接。
    int flags = fcntl(socket, F_GETFL, 0);
    fcntl(socket, F_SETFL, O_NONBLOCK|flags);

     

    ⑥connect:客户端请求连接
    -------------------------------------------------------------------------------------
    #include <sys/socket.h>
    int connect(      int socket,
            const struct sockaddr *address,
            size_t address_len);

    将参数socket指定的套接字连接到参数address指定的服务器套接字,
    address指向的结构长度有参数address_len指定。
    参数socket指定的套接字必须是通过socket条用获得的一个有效的文件描述符。

    connect成功时返回0,失败时返回-1。

    如果连接不能立刻建立,connect调用将阻塞一段不确定的超时时间。
    一旦这个超时时间到达,连接将被放弃,connect调用失败。

    但如果connect调用被一个信号中断,blah, blah——

     

    ⑦close:关闭套接字
    -------------------------------------------------------------------------------------
    调用close函数终止服务器与客户端上套接字的连接,就如同底层文件描述符进行关闭一样。
    连接的两端都关闭套接字。对服务器来说read调用返回0时关闭套接字。
    但如果套接字是一个面向连接类型的,并设置了SOCK_LINGER选项,
    close调用会在该套接字还有为传输数据时阻塞。

     

    ⑧主机字节序与网络字节序
    -------------------------------------------------------------------------------------
    例子:如果我们将0x1234abcd写入到以0x0000开始的内存中,则结果为
    big-endian little-endian
    0x0000 0x12 0xcd
    0x0001 0x23 0xab
    0x0002 0xab 0x34
    0x0003 0xcd 0x12
    x86系列CPU都是little-endian的字节序.
    网络字节顺序是TCP/IP中规定好的一种数据表示格式,
    它与具体的CPU类型、操作系统等无关,
    从而可以保证数据在不同主机之间传输时能够被正确解释。
    网络字节顺序采用big endian排序方式。

    #include <netinet/in.h>
    unsigned long int htonl(unsigned long int hostlong);
    unsigned short int htons(unsigned short int hostshort);
    unsigned long int ntohl(unsigned long int netlong);
    unsigned short ing ntohs(unsigned short int ntohs);

    htons 把unsigned short类型从主机序转换到网络序
    htonl 把unsigned long 类型从主机序转换到网络序
    ntohs 把unsigned short类型从网络序转换到主机序
    ntohl 把unsigned long 类型从网络序转换到主机序

    在使用little endian的系统中 这些函数会把字节序进行转换
    在使用big endian类型的系统中 这些函数会定义成空宏

     

    参考文献:

     1.《linux程序设计》第4版第15章

     2.http://www.cnblogs.com/jacktu/archive/2008/11/24/1339789.html

  • 相关阅读:
    socket选项设置
    shell 备忘录
    VIM中cscope和tags数据库的添加
    MFC程序设计中的BeginPaint/EndPaint和GetDC/ReleaseDC的使用
    shell 命令行参数解析
    do{...}while(0)用法总结
    0长度数组的使用
    在线帮助文档
    GCC编译器帮助文档
    几款优秀的Linux基准测试工具
  • 原文地址:https://www.cnblogs.com/xiashu/p/3553677.html
Copyright © 2011-2022 走看看