阻塞,非阻塞connect()和accept()

非阻塞connect()和accept()服务器

一.select()函数 
select()函数准备好读的条件: 
1>.套接口有数据可读 
2>.该链接的读这一半关闭(也就是接收了FIN的TCP链接)。对这样的套接口进行读操做将不阻塞并返回0(也就是返回EOF)。 
3>.该套接口是一个侦听套接口且已完成的链接数不为0。 
4>.其上有一个套接口错误待处理,对这样的套接口的读操做将不阻塞并返回-1,并设置errno,能够经过设置SO_ERROR选项调用getsockopt函数得到。异步

select()函数准备好写的条件:
1>.套接口有可用于写的空间。
2>.该链接的写这一半关闭,对这样的套接口进行写操做将产生SIGPIPE信号。
3>.该套接口使用非阻塞的方式connect创建链接,而且链接已经异步创建,或则connect已经以失败了结。
4>.其上有一个套接口错误待处理。
  • 1
  • 2
  • 3
  • 4
  • 5

二.accept()函数socket

1.阻塞模式tcp

阻塞模式下调用accept()函数,并且没有新链接时,进程会进入睡眠状态。函数

2.非阻塞模式.net

非阻塞模式下调用accept()函数,并且没有新链接时,将返回EWOULDBLOCK错误。线程

非阻塞模式select() + accept()日志

sockfd = listen_tcp(); //socket()、bind()、listen()code

FD_SET(sockfd, rset);blog

while(1){

ret = select(sockfd + 1, rset, NULL, NULL, timeout); // 等待某个事件发生:或是新链接、或是数据、或是FIN、或是RST到达


if(select()返回TIMEOUT){  //select()超时

    printf("日志打印");

    sleep(1);

    continue;

}

else if(FD_ISSET(sockfd,&rset)){    //判断句柄是否可读,返回真表明可读,可读表明有新链接。

    connfd = accept(sockfd, ...);


}

else if(select()返回错误){

    return -1;

}




pthread_create(thread_recv_data, connfd, ...);  // 建立线程处理新链接.

close();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

}

三.connect()函数

1.阻塞模式

客户端调用connect()函数将激发TCP的三路握手过程,但仅在链接创建成功或出错时才返回。返回的错误可能有如下几种状况:

1>.若是TCP客户端没有接收到SYN分节的响应,则返回ETIMEDOUT,阻塞模式的超时时间在75秒(4.4BSD内核)到几分钟之间。

2>.若是对客户的SYN的响应时RST,则代表该服务器主机在咱们指定的端口上没有进程在等待与之链接(例如服务器进程也许没有启动),这称为硬错,客
  • 1
  • 2
  • 3

户一接收到RST,立刻就返回错误ECONNREFUSED.

3>.若是某客户发出的SYN在中间的路由器上引起了一个目的地不可达ICMP错误,屡次尝试发送失败后返回错误号为EHOSTUNREACH或ENETUNREACH.
  • 1

附加:产生RST的三种状况,一是SYN到达某端口但此端口上没有正在侦听的服务器、二是TCP想取消一个已有链接、三是TCP接收了一个根本不存在的链接上的

分节。

2.非阻塞工做模式

调用connect()函数会马上返回EINPROCESS错误,但TCP通讯的三路握手过程正在进行,因此可使用select函数来检查这个链接是否创建成功。

源自Berkeley的实现有两条与select函数和非阻塞相关的规则:
  • 1

1>.当链接成功创建时,描述字变成可写。

2>.当链接创建出错时,描述字变成便可读又可写。getsockopt()函数的errno == 0表示只可写。

非阻塞模式 select() + connect()

while(1){

ret = connect();

if(errno == EINPROCESS){ //此时TCP的三路握手继续进行

    select(...) //等待某个事件发生:或是新链接、或是超时

    if(FD_ISSET(sockfd,&wset) ){ //判断句柄可写,不能表明创建链接成功。

        getsockopt(...);

        if(errno == 0){  //创建链接成功




        }


    }

    else if(select()返回TIMEOUT){

        sleep(1);

        continue();

    }

}

else if(ret == -1){

    //Connect  failed

}



pthread_create(thread_send_log, ...); //创建线程处理新链接

close();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

}

https://blog.csdn.net/bobkentblog/article/details/50850724

相关文章
相关标签/搜索