自己动手实现socket的各种超时控制
来源:互联网 发布:ubuntu 上网命令 编辑:程序博客网 时间:2024/06/04 18:51
在高并发的网络编程中,如果对socket的超时不加以控制,程序会死的很辛苦。
在这里,需要控制超时时间的地方基本上分为三个部分:连接超时、读超时以及写超时。
下面将按照上述超时问题依次解决之。
连接超时
处理连接超时有若干种方案,第一种比较trick,使用socket本身的属性进行设置。
可以使用该属性进行设置的原因是connect的内核实现(源文件地址)采用了如下的实现方式:
/* * Connect to a remote host. There is regrettably still a little * TCP 'magic' in here. */ int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) { //省略之前的代码 timeo = sock_sndtimeo(sk, flags & O_NONBLOCK); if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) { int writebias = (sk->sk_protocol == IPPROTO_TCP) && tcp_sk(sk)->fastopen_req && tcp_sk(sk)->fastopen_req->data ? 1 : 0; /* Error code is set above */ if (!timeo || !inet_wait_for_connect(sk, timeo, writebias)) goto out; err = sock_intr_errno(timeo); if (signal_pending(current)) goto out; } //省略之后的代码 } EXPORT_SYMBOL(__inet_stream_connect);该函数的实现使用了socket的发送超时时间的设定。
因此,对connect进行超时控制的时候,可以采用如下的代码对socket的发送超时时间进行设置,具体流程可以描述为:
- 创建socket
- 使用setsockopt函数设定socket的具体设置,在这里设定发送超时
- 最后使用connect执行连接的操作。
代码如下:
int sock_fd = socket(AF_INET, SOCK_STREAM, 0); if (sock_fd < 0) { perror("create sock_fd"); exit(-1); } struct sockaddr_in addr; bzero(&addr,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port=htons(g_conf.aod_port); addr.sin_addr.s_addr = inet_addr(g_conf.aod_host); struct timeval timeo = {0, 0}; socklen_t len = sizeof(timeo); timeo.tv_usec = 10*1000;//10ms setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, &timeo, len); if(connect(sock_fd, (sockaddr*)&addr,sizeof(addr))<0){ fprintf(,stdout,"%s","CONNECT WITH AOD SERVER FAILED"); return -1; }
另外一种对connect设定超时的方法是使用网上广为流传的select/poll方法。这种方法来自于connect函数的manuel,使用man connect,可以看见connect函数返回值的如下描述:
EINPROGRESS The socket is non-blocking and the connection cannot be completed immediately. It is possible to select(2) or poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsock- opt(2) to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the rea- son for the failure).根据上述的描述,我们可以使用connect的返回值做一些文章,从而完成对connect的设置。其实上述的手册已经给定了一个实现connect超时设定的基本步骤,这种方法比之前的方法复杂一些:
- 建立socket的文件描述符
- 将socket设置为非阻塞的连接模式
- 调用connect函数,对connect的返回值进行判定
- 使用select检查该socket的文件描述符是否可写
- 将socket重新设置为阻塞的模式
- 自己动手实现socket的各种超时控制
- java线程 超时控制的实现
- Java线程超时控制的实现
- Java线程超时控制的实现
- 使用非阻塞socket来控制connect的超时
- 如何控制C#Socket的连接超时时间
- c#关于socket连接超时控制的方案
- 自己动手实现简单权限控制
- 自己动手实现简单权限控制
- 自己动手实现简单权限控制
- 自己动手hellojni的各种细节
- MySQL的各种网络IO超时的用法和实现
- Linux下Socket连接超时的一种实现方法
- C++ SOCKET中实现超时的一种方法
- linux c实现超时、非阻塞socket的函数select
- Linux下Socket连接超时的一种实现方法
- Linux下Socket连接超时的一种实现方法
- JAVA SOCKET connect超时设置是如何实现的?
- python中的原始字符串"r"
- c++中win32控制台输出宽字符
- android 博客1
- 人,这一辈子
- Android AsyncTask的使用
- 自己动手实现socket的各种超时控制
- hdu2871 线段树之空间动态存储模拟
- CentOS5.8下用“软件包安装工具安装”总是提示:另一个目前运行的程序正在访问软件信息。
- Spring集成Quartz1.8.4版定时任务框架介绍
- Java的位运算符详解实例——与(&)、非(~)、或(|)、异或(^)
- C#中的快捷键,可以更方便的编写代码
- linux内核移植
- springmvc +mybatise 框架的搭建步骤
- libusb 加入到 Android