博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JAVA SOCKET connect超时设置是如何实现的?
阅读量:6890 次
发布时间:2019-06-27

本文共 2117 字,大约阅读时间需要 7 分钟。

  hot3.png

JAVA SOCKET编程中 SOCKET中connect方法是可以设置连接超时时间的,如下:

java.net.Socketpublic void connect(SocketAddress endpoint, int timeout) throws IOException

注:timeout为0表示不限超时 connect调用会一直阻塞直到连接建立或发生错误; 如果timeout>0 连接在timeout毫秒内没有建立,会返回抛出SocketTimeoutException异常。

而在Linux系统编程中 connect 系统调用是不能够设置超时时间的,API如下:

int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);

注:sockfd 是阻塞的

从TCP协议栈的角度考虑,连接建立需要三次握手,只要没有收到应答报文,那么就会重新发送(发送的时机需要深入Linux时钟机制);如果连接最终无法建立,那么TCP最终会放弃 connect 调用;对于基于 Berkeley BSD的系统,默认时间是 75秒; 这个时间对于应用来说太长了。

既然 Linux 没有提供一种控制 TCP协议栈 connect超时时间的 API, 那么该如何设置 connect 超时呢?

1、设置 fd 非阻塞, connect 调用立即返回,错误号为 EINPROGRESS

2、注册 fd 写事件 到 select 调用,同时设置超时时间为 timeout

查找 JDK 源码,看看 JAVA 是如何实现的?

相关文件: openjdk\jdk\src\share\transport\socket\socketTransport.c

                openjdk\jdk\src\solaris\transport\socket\socket_md.c

/*     * To do a timed connect we make the socket non-blocking     * and poll with a timeout;     */    if (attachTimeout > 0) {        dbgsysConfigureBlocking(socketFD, JNI_FALSE);    }    err = dbgsysConnect(socketFD, (struct sockaddr *)&sa, sizeof(sa));    if (err == DBG_EINPROGRESS && attachTimeout > 0) {        err = dbgsysFinishConnect(socketFD, (long)attachTimeout);        if (err == DBG_ETIMEOUT) {            dbgsysConfigureBlocking(socketFD, JNI_TRUE);            RETURN_ERROR(JDWPTRANSPORT_ERROR_TIMEOUT, "connect timed out");        }    }
intdbgsysFinishConnect(int fd, long timeout) {    int rv = dbgsysPoll(fd, 0, 1, timeout);    if (rv == 0) {        return DBG_ETIMEOUT;    }    if (rv > 0) {        return 0;    }    return rv;}
intdbgsysPoll(int fd, jboolean rd, jboolean wr, long timeout) {    struct pollfd fds[1];    int rv;    fds[0].fd = fd;    fds[0].events = 0;    if (rd) {        fds[0].events |= POLLIN;    }    if (wr) {        fds[0].events |= POLLOUT;    }    fds[0].revents = 0;    rv = poll(&fds[0], 1, timeout);    if (rv >= 0) {        rv = 0;        if (fds[0].revents & POLLIN) {            rv |= DBG_POLLIN;        }        if (fds[0].revents & POLLOUT) {            rv |= DBG_POLLOUT;        }    }    return rv;}
实现思路是一致的。

转载于:https://my.oschina.net/astute/blog/92339

你可能感兴趣的文章
微信小程序--倒计时封装
查看>>
区块链为品牌企业和用户解决“信任”危机
查看>>
redux学习笔记
查看>>
CrapApi 接口测试增强插件-下载、安装、使用文档 - v2.0.0
查看>>
在树莓派上搭建个人网盘
查看>>
AssociatedObject关联对象原理实现
查看>>
带你手写vnode到renderDom
查看>>
区块链是如何帮助企业实现品牌承诺
查看>>
SQLServer之创建存储过程
查看>>
JS-this
查看>>
JS中的双向数据绑定及Object.defineProperty方法
查看>>
java 常用jar包
查看>>
java基础知识: day3-对象和类
查看>>
深入浅出 Java 并发编程 (2)
查看>>
D2 日报 2019年5月14日
查看>>
js知识梳理1:理解对象的属性特性
查看>>
谈谈 "JS 和 设计泛型"
查看>>
一道数学题的思考
查看>>
原生JS 编写移动端 tab选项卡
查看>>
注解的使用踩过坑
查看>>