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

  • 相关阅读:
    CS224n, lec 10, NMT & Seq2Seq Attn
    CS231n笔记 Lecture 11, Detection and Segmentation
    CS231n笔记 Lecture 10, Recurrent Neural Networks
    CS231n笔记 Lecture 9, CNN Architectures
    CS231n笔记 Lecture 8, Deep Learning Software
    CS231n笔记 Lecture 7, Training Neural Networks, Part 2
    pytorch坑点排雷
    Sorry, Ubuntu 17.10 has experienced an internal error
    VSCode配置python插件
    tmux配置与使用
  • 原文地址:https://www.cnblogs.com/xiashu/p/3553677.html
Copyright © 2011-2022 走看看