zoukankan      html  css  js  c++  java
  • Linux 网络编程基础(3) -- 数据的IO

    首先介绍两个数据结构及相关的操作函数:struct iovec、struct msghdr

    struct iovec {

      void * iov_base;    /*向量的缓冲地址*/

      size_t iov_len;   /*向量缓冲区的大小,以字节为单位*/

    };

    iovec定义在linux/include/uio.h中,此数据结构与readv()和writev()联合使用。

    ssize_t readv(int s, const struct iovec *vector, int count);

    返回值为成功接收的字节数。   s: 文件描述符         vector:iovec数组的起始地址                 count:iovec数组的元素个数。

    ssize_t writev(int fd, const iovec *vector, int count);

    返回值为成功发送的字节数。   fd:文件描述符         vector:发送数据的vector数组地址          count:iovec数组的元素个数

    应用的例子:

    /*
        服务器端代码
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <sys/uio.h>
    #include <netinet/in.h>
    #define Serv_Port  8888
    #define BackLog 5
    void process_client_vector(int sock_cli);
    
    int  main(char *argv[], int argc)
    {
        int sock_serv, sock_cli;
        struct sockaddr_in  server_addr;
        struct sockaddr_in  client_addr;
        
        int err;
        pid_t handle_client_pid;
    
        sock_serv = socket(AF_INET, SOCK_STREAM, 0);
        if(sock_serv < 0){
            printf("Error When build Socket
    ");
            return 1;
        }
    
        bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(Serv_Port);
        server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        err = bind(sock_serv, (struct sockaddr*)&server_addr, sizeof(server_addr));
        if(err < 0){
            printf("Error When Bind
    ");
            return 1;
        }
    
        err = listen(sock_serv, BackLog);
        if(err < 0){
            printf("Error When Listen
    ");
            return 1;
        }
    
    //    while(1){
            int addrlen = sizeof(struct sockaddr);
            printf("Waiteing... ...
    ");
            sock_cli = accept(sock_serv, (struct sockaddr*)&client_addr, &addrlen);
    
            if(sock_cli < 0)
                ;//continue;
            handle_client_pid = fork();
            if(handle_client_pid == 0){
                close(sock_serv);
                process_client_vector(sock_cli);
            }
            else
                close(sock_cli);
    //    }
    }
    
    void process_client_vector(int sock_cli)
    {
        int number;
        char str;
        char ch;
        int i = 0;
        printf("One client is Accpted
    ");
        struct iovec *recv_vector = (struct iovec*)malloc(3*sizeof(struct iovec));
    
        if(!recv_vector){
            printf("NO Enough Space Here
    ");
            return;
        }
    
        recv_vector[0].iov_base = &number;
        recv_vector[0].iov_len = sizeof(number);
        
        recv_vector[1].iov_base = &str;
        recv_vector[1].iov_len = sizeof(str);
        
        recv_vector[2].iov_base = &ch;
        recv_vector[2].iov_len = sizeof(ch);
    
        ssize_t size = readv(sock_cli, recv_vector, 3);
        printf("RECVED: Number%d  STR: %c   CHAR:%c
    ",number,str,ch);
    
    }
    /*
        客户器端代码
    */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <strings.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <sys/uio.h>
    #include <netinet/in.h>
    
    #define Serv_Port 8888
    void process_server_vector(int sock_cli);
    
    int main(char *argv[], int argc)
    {
        struct sockaddr_in server_addr;
        int err;
        int sock_cli;
    
        sock_cli = socket(AF_INET, SOCK_STREAM, 0);
        if(sock_cli < 0){
            printf("Error When Socket()
    ");
            return 1;
        }
    
        bzero(&server_addr, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(Serv_Port);
        inet_pton(AF_INET, "127.0.0.1",&server_addr.sin_addr);
    
        connect(sock_cli, (struct sockaddr *)&server_addr, sizeof(server_addr));
    
        process_server_vector(sock_cli);
    
        close(sock_cli);
    
        return 0;
    }
    
    void process_server_vector(int sock_cli)
    {
        int number = 10;
        char str = 'K';
        char ch = 'M';
        ssize_t size = 0;
    
        struct iovec *vector = (struct iovec *)malloc(3*sizeof(struct iovec));
    
        vector[0].iov_base = &number;
        vector[0].iov_len = sizeof(number);
        
        vector[1].iov_base = &str;
        vector[1].iov_len = sizeof(str);
        
        vector[2].iov_base = &ch;
        vector[2].iov_len = sizeof(ch);
    
        size = writev(sock_cli, vector, 3);
        if(size < 0 )
            printf("Writev Error
    ");
    }

     msghdr 结构体定义在linux/include/socket.h中

     struct msghdr {
              void            *msg_name;      /* ptr to socket address structure */
              int             msg_namelen;    /* size of socket address structure */
              struct iovec    *msg_iov;       /* scatter/gather array */
              __kernel_size_t msg_iovlen;     /* # elements in msg_iov */
              void            *msg_control;   /* ancillary data */
              __kernel_size_t msg_controllen; /* ancillary data buffer length */
              unsigned int    msg_flags;      /* flags on received message */
      };

    这个数据结构如果不考虑msg_falsgs,与struct iovec的用法并没有很大的差别,操作这个数据结构的函数:
    #include<sys/uio.h>
    ssize_t recvmsg(int s, const struct msghdr *msg, int flags);
    s: 套接字 msg:承接数据的消息数据结构 flags:没有很大的意义,
    ssize_t sendmsg(int s, const struct msghdr *msg, int flags );
    s: 套接字             msg:承接数据的消息数据结构   flags:决定以什么方式发送数据
    readmsg的接收方式取决于msg结构中msg_flags的值,这也是readmsg()与函数sendmsg()的不同的地方,sendmsg()函数的发送方式有参数决定。

    在没有介绍套接字的选项前,先不对msghdr的相关代码编写进行实践,因为msghdr中的msg_name,msg_control,msg_flags 等成员的设定与当前使用的协议是相关的,待以后把套接字的选项介绍完后,在深入探究msghdr的使用。

    除了上述介绍的几个函数,还有很多的IO函数,现总结如下:



    int read(int fd, void * buffer, int nbyte);
    int write(int handle, void *buf, int nbyte);
    这两个函数可以用于任何的描述符,可以用于文件,标准输入输出,和套接字。

    readv(), writev(),recvmsg(),sendmsg()的具体函数参考上面的具体内容。

    int recvfrom(int s,void *buf,int len,unsigned int flags ,struct sockaddr *from ,int *fromlen);
    s: 套接字  buf:数据接收缓冲区  len:接收数据长度 flags:是以下一个或者多个标志的组合体,可通过or操作连在一起
    from:数据的来源的地址 fromlen: 地址长度。

     
  • 相关阅读:
    TAM实施范例
    xmanager连接到RHEL6.
    TAM安装过程中遇到的问题
    db29.1FP2升级FP12
    WAS常见问题及解答
    在 Lotus Quickr for Domino 环境中使用 Tivoli Access Manager WebSEAL 作为反向代理服务器
    TAM包含的内容全面的指南自IBM
    Setting up the Web Admin Tool in LDAP 6.x to communicate via SSL
    oracle字符集。
    redhat中设置环境变量PATH的方法和只显示目录的Tree
  • 原文地址:https://www.cnblogs.com/tju-gsp/p/3655015.html
Copyright © 2011-2022 走看看