zoukankan      html  css  js  c++  java
  • Linux IO模型漫谈(3) 阻塞式IO实现

    在理解代码前有几个函数先说一下:

    1 sockaddr_in 套接字地址结构

    struct sockaddr_in {
        uint8_t         sin_len;        //长度字段,这个sockaddr_in结构的长度,一般不用设置和检查它
        sa_family_t     sin_family;     //协议族,TCP,UDP等协议族就设置为AF_INET  
        in_port_t       sin_port;       //端口号
        
        struct in_addr  sin_addr;       //32位的IPv4地址
        
        char            sin_zero(8);    //未使用
    
    }

    POSIX规范只需要指定其中的sin_family, sin_port, sin_addr三个字段

    这个结构非常重要!!

    2 socket函数(创建套接字)

    #include <sys/socket.h>
    
    int socket(int family, int type, int protocol)

    参数解释:

    family:协议族,和sockaddr_in中的sin_family一个意思

    type: 指明套接字类型

    Protocol:通常赋值为0

    这个函数是所有套接字编程的入口,创建套接字。

    3 htons函数

    这个函数是将本地字节序列转换为网络字节序列,简单来说,就是将一个数的高低位互换

    (如12 34 -> 3412)

    这个函数在给servaddr_in赋值的时候会用到

    下面这个程序包含了基本的IO操作,说明以注释的形式加在代码中;

    服务器端:

    #include <stdio.h>     //这个头包含了最简单的输入和输出
    #include <sys/types.h>    //这个头包含了系统调用的大量数据结构
    #include <sys/socket.h>   //这个头包含了socket的结构
    #include <netinet/in.h>   //这个头包含了internet地址解析的一些数据结构
    #include <string.h>
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
        int listenfd, portno;  //文件描述符
        int clifd, clilen;
        struct sockaddr_in serv_addr,cli_addr;  //socketadd_in定义在netinet/in.h中
        listenfd = socket(AF_INET, SOCK_STREAM, 0);  //创建一个套接字
        
        bzero((char *) &serv_addr, sizeof(serv_addr));  //初始化
        serv_addr.sin_family = AF_INET;     //设置协议族
        serv_addr.sin_port = htons(7777);      //设置端口
        serv_addr.sin_addr.s_addr = INADDR_ANY;  //设置socket的另一端的地址信息,由于这里是server程序,因此设置为ANY
        
        bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)); //绑定地址,将本地协议地址赋予一个套接字
        listen(listenfd, 5);  //监听socket,第二个参数规定了内核应该为相应套接字排队的最大连接数个数,不要设置为0
        
        clilen = sizeof(cli_addr);
        clifd = accept(listenfd, (struct sockaddr *) &cli_addr, &clilen); //当有客户端连接的时候,进入连接队列
        
        char buffer[256];
        bzero(buffer, 256);
        read(clifd, buffer, 255);   //读取客户端发送的消息
        printf("The Message is:%s\r\n", buffer);
        
        write(clifd, "I get the message", 17); //往客户端发送消息
        
        close(clifd);
        close(listenfd);
        return 0;
    
    }

    server的流程基本是这样的:

    clip_image001

    客户端:

    #include <stdio.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <unistd.h>
    
    int main(int argc, char* argv[])
    {
        int socketfd;
        socketfd = socket(AF_INET, SOCK_STREAM, 0);
    		
        struct sockaddr_in serv_addr;
    		
        bzero((char *)&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(7777);
    		
        connect(socketfd,(struct sockaddr *)  &serv_addr, sizeof(serv_addr));
    		
        write(socketfd, "client message", 14);
    		
        char buffer[256];
        bzero(buffer, 256);
        read(socketfd, buffer, 255);
    		
        printf("server return message:%s\r\n", buffer);
    		
        return 0;
    }

    客户端的流程如下;

    clip_image002

    实时了解作者更多技术文章,技术心得,请关注微信公众号“轩脉刃的刀光剑影”

    本文基于署名-非商业性使用 3.0许可协议发布,欢迎转载,演绎,但是必须保留本文的署名叶剑峰(包含链接http://www.cnblogs.com/yjf512/),且不得用于商业目的。如您有任何疑问或者授权方面的协商,请与我联系

  • 相关阅读:
    CPU使用率呈现正弦曲线
    编写一个简单的http server(Linux, gcc)
    c#操作 文件操作
    Javascript 数字时钟
    .net 中读取文本文件
    c# 常用字符串函数
    I2C总线之(三)以C语言理解IIC
    典型的多线程操作界面的例子
    uvm_common_phase.svh
    uvm_task_phase.svh
  • 原文地址:https://www.cnblogs.com/yjf512/p/2534178.html
Copyright © 2011-2022 走看看