I/O模型

1、UDP流程2
     提醒:客户端的sendto永远成功,即使服务端没运行,也不报错,所以有了第二种流程。

     服务器 客户端
     socket(SOCK_DGRAM)                 socket(SOCK_DGRAM)
       |                                                         |
     bind                                                   connect
       |                                                         |
     while(1){                                          while(1) {
       |                                                         |
recvfrom(保存对方地址)                     send
       |                                                         |
     sendto                                             recv}
       }                                                        |
       |                                                       close
     close                                                                    

备注:connect不是建立连接(抓不到三次握手的数据包),是固定接收方,假如接收方没运行,send报错
connect函数只能用于TCP程序??不对      

2. 套接字缓冲区
  ---流式套接字在内核中有发送缓冲区和接收缓冲区
     ---send函数把数据发送到发送缓冲区,就成功返回。若发送缓冲区满了,send函数阻塞。
        ----send发送的数据,是先发到对方的接收缓冲区,把对方接收缓冲区填满后,自己的发送缓冲区开始累积,直到自己的发送缓冲区满,send才阻塞
            ----netstat -anpt  (该命令可以看套接字的状态,比如地址、缓冲区等)
     ---recv函数是从接收缓冲区中取出数据。若接收缓冲区空,recv函数阻塞。
  ---数据报套接字没有发送缓冲区,所以UDP的发送,永远不会阻塞
 
 
3.IO模型
  --阻塞IO(假如对方出故障,可能无限制阻塞,默认)

  --非阻塞IO(循环调函数,浪费CPU,用的少)
    ---通过fcntl可以把套接字设置成非阻塞模式
      int flag;
      flag = fcntl(sockfd, F_GETFL, 0);
      flag |= O_NONBLOCK;    //#define O_NONBLOCK    00004000    倒数11位(从0开始数)默认是0,代表套接字默认阻塞,改成1就非阻塞
      fcntl(sockfd, F_SETFL, flag);

    ---I/O多路复用
        核心思想:使用单进程实现多进程的效果。
        实现方法:
            ---构造一张有关描述符的表
                fd_set fs;                    //相当于int fs[1024];数组的值是不确定的
                FD_ZERO(&fs);      // 数组清零     fs[0]=0.....  
                FD_SET(0,&fs);        //数组写入1 fs[0]=1
                FD_SET(listendfd,&fs);//fs[listendfd]=-1
          
          ---调用select函数
                ----selsct调用,进程会阻塞
                ----任何一个描述符有数据(就绪),进程都会被唤醒(select用一个进程,实现了多进程的效果)
                ----返回值,有数据的描述符个数(通过返回值不知道那个描述符有数据)
                ----描述符表中,没数据的1,被清0(是1的位置,有数据)
            
        ---循环处理描述符表中保留的1
                for(i=0;i<=maxfd;i++)
                {
                        if(FD_ISSET(i,&fs)==1)//(fs[i]==1)
                        {    
                                if(i==0)
                                {
                                    fgets();
                                }    
                                if(i==listenfd)
                                {
                                    connfd=accept(listenfd);
                                    close(connfd);
                                }
                        }
                }


    ---信号驱动IO
       ----特指信号SIGIO,编号29
       ----异步模式, 有数据时,内核给进程发SIGIO信号,程序执行信号函数


4.服务器模型
  ---循环服务器
     ---TCP的循环服务器很少用(客户端独占服务器,退出后,别的客户端才能连上)
     ---UDP的循环服务器可以使用(UDP协议无连接,可以同时和多个客户端通信)

  ---并发服务器(TCP)
     思想:服务器接受客户端的连接请求后创建子进程来为客户端服务
     缺点:为了响应客户机的请求,服务器要创建子进程来处理。 如果有多个客户端的话,服务器端需要创建多个子进程。过多的子进程会影响服务器端的运行效率。

     --流程如下:
        备注:当给同一个进程,在很短的时间内连续发送同样的信号,操作系统会吧很多信号合并,少发,所以要while(waitpid()>0);当没有僵尸时,wait返回0,信号函数执行结束
    void handel_zombie(int sig)
    {    
            while(waitpid(-1,NULL,WNOHANG)>0);
    }        
     socket(...);
    signal(....);
     listen(...);
     while(1) {
      accept(...);
 if (fork() = = 0) {
          while(1) { recv(...); process(...); send(...); }
          close(...);
          exit(...);
        }
        close(...);
     }



非阻塞IO,信号驱动io











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_27205523

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值