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 ...
随机推荐
- PARSEC-3.0编译错误
OS: Ubuntu 14.04 LTS (x86_64) ***error 1 OpenSSL 1.0.1e 与 perl5.18 不兼容 POD document had syntax error ...
- Outline of Apache Jena Notes
1 description 这篇是语义网应用框架Apache Jena学习记录的索引. 初始动机见Apache Jena - A Bootstrap 2 Content 内容组织基本上遵循Jena首页 ...
- C#编程语言与面向对象——委托
委托(delegate)也可以看成是一种数据类型,可以用于定义变量,但它是一种特殊的数据类型,所定义的变量能接收的数值只能是个函数,更确切地说,委托类型的变量可以接收一个函数的地址. 简单地说 委托变 ...
- 安装 modelsim 10.4
安装教程: http://jingyan.baidu.com/article/da1091fb30d880027849d63a.html 在安装的过程中出现cmd乱(即在输入页面上停留字符),还有吱吱 ...
- LintCode Find Minimum In Rotated Sorted Array
1. 画图, 直观. 2. 讨论数组为空或者个数为零. 3. 讨论首尾, 若为翻转过的则进行查找直到最后两个数进行比较, 取小者. public class Solution { /** * @par ...
- jquery的ajax和jsonp的写法
交互 ajax jsonp ajax跟之前一模一样 $(document).ready(function(){ $.ajax({ url:'get.php', ...
- JavaScript面向对象,及面向对象的特点,和如何构造函数
1.面向对象和面向过程的区别 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了: 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是 ...
- ios 多种传值方式
在网上看了看传值方法,没有找到完整的.在这把自己看到的几种传值方法写写吧. 1 . 属性传值 2 . 通知传值 3 . 代理传值 4 . block传值 5 . 单列传值 6 . ShareAppli ...
- Git 基础
取得项目的 Git 仓库 有两种取得 Git 项目仓库的方法.第一种是在现存的目录下,通过导入所有文件来创建新的 Git 仓库.第二种是从已有的 Git 仓库克隆出一个新的镜像仓库来. 在工作目录中初 ...
- mysql 5.7修改密码
关闭正在运行的 MySQL : [root@www.woai.it ~]# service mysql stop 运行 [root@www.woai.it ~]# mysqld_safe --skip ...