UNIX网络编程-非阻塞connect和非阻塞accept
1、非阻塞connect
在看了很多资料之后,我自己的理解是:在socket发起一次连接的时候,这个过程需要一段时间来将三次握手的过程走完,如果在网络状况不好或者是其他的一些情况下,这个过程需要比较长的时间,我们在连接之前将socket设置为非阻塞模式之后,调用connect函数之后,立即返回,如果成功返回0,如果不成功则返回EINPROGRESS,这个值表明连接正在进行,我们可以设置一个超时时间,然后在这个时间段内不停的检查socket是否连接上了,如果在这个时间段内还没有连上,则返回失败。在这个检查的过程中我们可以做一些其他事情,而不必等待连接。
实现这个检查过程,有两种方式:一种方法是用一个while循环来做,另一种方法是通过select来做。
方法一:
if (connect(sockfd, (struct sockaddr *) &address, sizeof(address)) < )
{
err = errno; if (err != EINPROGRESS)
{
socket_ok = -;
}
else
{
while (true) /* is noblocking connect, check it until ok or timeout */
{
connect(sockfd, (struct sockaddr *) &address, sizeof(address)); err = errno;
switch (err)
{
case EISCONN: /* connect ok */
connect_ok = ;
break; case EALREADY: /* is connecting, need to check again */
usleep();
break; default:
connect_ok = -;
break;
} if (connect_ok == )
{
break;
} if (connect_ok == -)
{
break;
} if ( (timeout > ) && ((time(NULL) - begin_time) > timeout) )
{
break;
}
}
}
}
else /* Connect successful immediately */
{
connect_ok = ;
}
方法二:
int CTCPConn::AsynConnectToServer(timeval tmConnTimeout)
{
int nRet = -; if( m_nEntityID <= )
{
return -;
} if( m_stSocket.CreateClient() )
{
LOG("Conn create client of DBServer %d failed.\n", m_nEntityID);
return -;
} nRet = m_stSocket.AsynConnectTo(m_ulIPAddr, m_unPort); // 返回-1表示正在连接
if ( nRet != - )
{
return nRet;
} fd_set writeSets;
SOCKET iSocketFD = m_stSocket.GetSocketFD();
FD_ZERO(&writeSets);
FD_SET(iSocketFD, &writeSets); nRet = select(iSocketFD + , NULL, &writeSets, NULL, &tmConnTimeout); if ( nRet <= )
{
m_stSocket.Close();
return -;
} if ( !FD_ISSET(iSocketFD, &writeSets) )
{
m_stSocket.Close();
return -;
} #ifdef WIN32
int nLen = sizeof(nRet);
getsockopt(iSocketFD, SOL_SOCKET, SO_ERROR, (char*)&nRet, &nLen);
#else
socklen_t nLen = sizeof(socklen_t);
getsockopt(iSocketFD, SOL_SOCKET, SO_ERROR, (char*)&nRet, &nLen);
#endif if( nRet != )
{
m_stSocket.Close();
return -;
} m_stSocket.SetConnected(); return ;
}
用select函数检查是否可写,这里可以设置一个超时时间,如果连接成功了的话,则socket变为可写的,select函数是可以检测到。检测到可写之后,用getsockopt函数来获取选项值,如果为0,则证明连接成功。
非阻塞连接的用途:
(1)可以在socket进行三次握手的时候干其他事情,不至于阻塞;
(2)可以同时进行多个连接,在web应用中比较常见(本人自己认为,浏览器就用到了这个,但具体怎么做的没有去了解)
(3)可以设置较短的超时时间,一般connect设计的时候都会有一个超时时间,会比较长,设置为非阻塞我们就可以自己来设定超时时间。
2、非阻塞accept
非阻塞accept主要用来解决以下问题:
用select检测socket状态,如果有连接就调用accept,这样如果在select检测到由连接请求,在调用accept之前,这个请求断开了,然后调用accept的时候就会阻塞在哪里,除非这时有另外一个连接请求,如果没有,则一直被阻塞在那里。(本人以为如果把accept单独放在一个线程中,不会出现以上问题,就是不明白这样做有什么坏处)。
UNIX网络编程-非阻塞connect和非阻塞accept的更多相关文章
- UNIX网络编程——UDP 的connect函数(改进版)
上一篇我们提到,除非套接字已连接,否则异步错误是不会返回到UDP套接字的.我们确实可以给UDP套接字调用connect,然而这样做的结果却与TCP连接大相径庭:没有三次握手.内核只是检查是否存在立即可 ...
- UNIX网络编程——非阻塞connect:时间获取客户程序
#include "unp.h" int connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec) ...
- UNIX网络编程——非阻塞connect
当在一个非阻塞的TCP套接字上调用connect时,connect将立即返回一个EINPROGRESS错误,不过已经发起的TCP三次握手继续进行.我们接着使用select检测这个连接或成功或失败的已建 ...
- unix网络编程 str_cli epoll 非阻塞版本
unix网络编程 str_cli epoll 非阻塞版本 unix网络编程str_cli使用epoll实现讲了使用epoll配合阻塞io来实现str_cli,这个版本是配合非阻塞io. 可以看到采用非 ...
- UNIX网络编程---传输层:TCP、UDP、SCTP(二)
UNIX网络编程----传输层:TCP.UDP.SCTP 一.概述 本章的焦点是传输层:包括TCP.UDP.和SCTP(流控制传输协议).SCTP是一个较新的协议,最初设计用于跨因特网传输电话信令. ...
- UNIX网络编程中的需要注意的问题
字节流套接字上调用read或write,输入或输出的字节数可能比请求的数量少,这个现象的原因在于内核中用于套接字的缓冲区可能已经达到了极限.此时所需要的是调用者再次调用read或write函数.这个现 ...
- 【unix网络编程第三版】阅读笔记(五):I/O复用:select和poll函数
本博文主要针对UNP一书中的第六章内容来聊聊I/O复用技术以及其在网络编程中的实现 1. I/O复用技术 I/O多路复用是指内核一旦发现进程指定的一个或者多个I/O条件准备就绪,它就通知该进程.I/O ...
- UNIX网络编程——使用select函数编写客户端和服务器
首先看原先<UNIX网络编程--并发服务器(TCP)>的代码,服务器代码serv.c: #include<stdio.h> #include<sys/types.h> ...
- UNIX网络编程——并发服务器(TCP)
在迭代服务器中,服务器只能处理一个客户端的请求,如何同时服务多个客户端呢?在未讲到select/poll/epoll等高级IO之前,比较老土的办法是使用fork来实现. 网络服务器通常用fork来同时 ...
- 《Unix 网络编程》08:基本UDP套接字编程
基本UDP套接字编程 系列文章导航:<Unix 网络编程>笔记 UDP 概述 流程图 recvfrom 和 sendto #include <sys/socket.h> ssi ...
随机推荐
- android gradle的全局管理
转自:https://github.com/stormzhang 工程目录下建立baseConfig.gradle文件 内容如下 ext { android = [compileSdkVersion: ...
- python中try except执行顺序
python中try except finally的执行顺序 先执行try中语句 如果try中抛出异常, 执行异常中语句. 如果try 或 except 中没有return语句,执行完try 或者 e ...
- 测试cookie的读写
js文件使用utf8编码 <p><img id="img" onclick="javascript:var s=document.createEleme ...
- 八皇后—Java
package queen; public class queen { static boolean col[] = new boolean[8]; static boolean main_diago ...
- Adobe Flash builder 4的序列号
下载flex 4 之后,需要输入注册码(如果购买了正版就要选择第二个的单选框,无需输入注册码了) 1424-4258-9368-0713-8534-5128 1424-4806-8312-7960-9 ...
- 数据库SQL优化总结
1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- wininet异步InternetReadFile和超时相关问题
wininet是对socket的封装 主要流程为创建,连接,发送,接收,关闭几个过程 所以在回调函数InternetStatusCallback中可以检测到dwInternetStatus #defi ...
- js本地图片预览
相信大家都遇到过上传图片之前预览,网上找了很多,但都不是所有浏览器都支持,不过后来找到一个,但自己没有完全实验. 代码如下: <script> //使用IE条件注释来判断是否IE6,通过判 ...
- Android——通讯录
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- 在shell script中进行数值运算的两种方法
方法1:使用"$((计算式))"的方式进行数值运算,不需要使用declare命令显示声明数值型变量来存储计算结果: 方法2:使用declare命令配合"-i"选 ...