首页 存档 技术 查看内容

5种服务器网络编程模型讲解

2018-3-30 13:00 |来自: 互联网 400 0

摘要: 1.同步阻塞迭代模型 同步阻塞迭代模型是最简单的一种IO模型。 其核心代码如下: bind(srvfd); listen(srvfd); for(;;){ clifd = accept(srvfd,...); //开始接受客户端来的连接 read(clifd,buf,...); //从客户端读 ...

1.同步阻塞迭代模型


同步阻塞迭代模型是最简单的一种IO模型。


其核心代码如下:

bind(srvfd);
listen(srvfd);
for(;;){
    clifd = accept(srvfd,...); //开始接受客户端来的连接
    read(clifd,buf,...);       //从客户端读取数据
    dosomthingonbuf(buf);  
    write(clifd,buf)          //发送数据到客户端
}

上面的程序存在如下一些弊端:


1)如果没有客户端的连接请求,进程会阻塞在accept系统调用处,程序不能执行其他任何操作。(系统调用使得程序从用户态陷入内核态,具体请参考:程序员的自我修养)


2)在与客户端建立好一条链路后,通过read系统调用从客户端接受数据,而客户端合适发送数据过来是不可控的。如果客户端迟迟不发生数据过来,则程序同样会阻塞在read调用,此时,如果另外的客户端来尝试连接时,都会失败。


3)同样的道理,write系统调用也会使得程序出现阻塞(例如:客户端接受数据异常缓慢,导致写缓冲区满,数据迟迟发送不出)。


2.多进程并发模型


同步阻塞迭代模型有诸多缺点。多进程并发模型在同步阻塞迭代模型的基础上进行了一些改进,以避免是程序阻塞在read系统调用上。


多进程模型核心代码如下:

bind(srvfd);
listen(srvfd);
for(;;){
    clifd = accept(srvfd,...); //开始接受客户端来的连接
    ret = fork();
    switch( ret )
    {
      case -1 :
        do_err_handler();
        break;
      case 0  :   // 子进程
        client_handler(clifd);
        break ;
      default :   // 父进程
        close(clifd);
        continue ; 
    }
}
//======================================================
void client_handler(clifd){
    read(clifd,buf,...);       //从客户端读取数据
    dosomthingonbuf(buf);  
    write(clifd,buf)          //发送数据到客户端
}

上述程序在accept系统调用时,如果没有客户端来建立连接,择会阻塞在accept处。一旦某个客户端连接建立起来,则立即开启一个新的进程来处理与这个客户的数据交互。避免程序阻塞在read调用,而影响其他客户端的连接。


3.多线程并发模型


在多进程并发模型中,每一个客户端连接开启fork一个进程,虽然linux中引入了写实拷贝机制,大大降低了fork一个子进程的消耗,但若客户端连接较大,则系统依然将不堪负重。通过多线程(或线程池)并发模型,可以在一定程度上改善这一问题。


在服务端的线程模型实现方式一般有三种:


(1)按需生成(来一个连接生成一个线程)


(2)线程池(预先生成很多线程)


(3)Leader follower(LF)


为简单起见,以第一种为例,其核心代码如下:

void *thread_callback( void *args ) //线程回调函数
{
        int clifd = *(int *)args ;
        client_handler(clifd);
}
//===============================================================
void client_handler(clifd){
    read(clifd,buf,...);       //从客户端读取数据
    dosomthingonbuf(buf);  
    write(clifd,buf)          //发送数据到客户端
}
//===============================================================
bind(srvfd);
listen(srvfd);
for(;;){
    clifd = accept();
    pthread_create(...,thread_callback,
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部