AIO 开始不定时的抛异常: java.io.IOException: 指定的网络名不再可用

本文探讨了在网络编程中遇到的TCP连接异常关闭问题,特别是在使用完成端口(IOCP)模式下出现的ERROR_NETNAME_DELETED(64错误)。通过对测试场景的详细分析,揭示了客户端处理速度与服务器响应之间的关联,并提供了降低服务器发送速率以匹配客户端接收能力的解决方案。

一天里会抛出几个这样的错误,但发现服务还在正常的运行。

 

java.io.IOException: 指定的网络名不再可用。

        at sun.nio.ch.Iocp.translateErrorToIOException(Unknown Source)
        at sun.nio.ch.Iocp.access$700(Unknown Source)
        at sun.nio.ch.Iocp$EventHandlerTask.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)

 

在本地用ab进行并发测试的时候,比如: ab -n 2000 -c 200 -k http://xxx/....

当还没有运行完的时候,按Ctrl + C,服务端程序也会抛出这个异常。

说明,有可能是在发起TCP(这个可能性大一些)或关闭TCP的时候,握手没有完成。

 

由于在windows上,底层用Iocp实现,通过网上搜索:iocp 指定的网络名不再可用,知道了这个错误的iocp错误码:64,然后搜索:iocp 错误 64,找到几篇比较有价值的文章,下面是摘抄的一部分重点:

 

来源:http://topic.youkuaiyun.com/u/20080606/11/cdaaccab-e4b0-4e67-9194-8107a019a1e9.html

 

我们使用完成端口模式编写了一个提供下载的服务器,然后编写了一个测试程序模拟100个客户端来从服务器下载文件,测试程序是通过开启100个线程,以每个线程当作一个客户端来下载文件的,但是测试过程中出现了以下问题:
经过在多台机器上的测试,只有少数机器出现以下问题,其中最显著的机器网速是10mbps的。
在成功连接后,文件传输过程中,服务器工作者线程的GetQueuedCompletionStatus处出现了64错误(ERROR_NETNAME_DELETED),但是客户端没有退出也没有任何错误输出,把客户端线程数减少到10个时就不会出现这个问题。
哪位朋友知道这种问题的原因,请帮忙分析一下吧,谢谢大家了!(如果是不能解决的问题,也得有合理的解释,不然没法和客户解释)


回复1:
ERROR_NETNAME_DELETED(64 #错误)在我的测试中是在 client 非正常关闭 TCP 通道时会出现,即关闭的 4 次握手没有正常完成时出现。如果很好的(graceful)完成关闭,比如c/s双方shutdown等, GetQueuedCompletionStatus会成功,会pNumberOfBytes = 0   
  但是很多时候 TCP 通道会非正常关闭,这很正常,所以出现 ERROR_NETNAME_DELETED 也没有什么可怕的。

 

回复2:
这个错误,我也碰到过,分析得到的结论主要还是因为IOCP满负载工作,特别是有众多的未决IO的时候,可能某一个客户端在长时间内得不到影响就会由内核因超时而断掉。建议在这个时候,使用NetStat 查看一下相关的连接状态。

 

回复3:
我再描述一下测试发现的问题的一点规律吧。
在网速100mbps的机子上基本不出现该问题,基本上总是网速为10mbps的机子出现这个问题。还有就是在10mbps的机子上测试发现,模拟100个至少有20个左右出现问题,随着模拟数降低,出现问题的个数也会减少,减少到20个时,测试10次中只有一次出现了一个该问题,减少到10个时,在测试中没出现过该问题。
还有就是请大家注意一下,服务器出现64错误时:
1.客户端使用非阻塞型套接字时,客户端有超时输出
2.客户端使用阻塞型套接字时,客户端没有相应的输出
由此我认为服务器出现64错误时客户端并没有退出,而是阻塞住了。


回复4:
问题基本已经确定,应该是由于客户端的处理速度太慢,缓冲区总是满的,导致服务器认为对方结束了连接。
我是这样确定问题的,现在贴出来希望能给大家一些帮助:
由于iocp的不可控,不方便跟踪,于是服务器端我们采用普通模式,即接到一个连接就开一个线程来处理。然后跟踪调试服务器端,而客户端采用写log的方式来跟踪,最后确定出64错误的连接在服务器端是出现在文件传输过程中的send处,而服务器出64错误的时候,客户端是阻塞在recv处的(我测试时使用的是阻塞型套接字)。
之后就采用降低服务器发送速度的方式(比如在send前Sleep一下)测试一下,经过多次验证,发现只要服务器发送的速度在客户端的可承受范围内的时候(比如客户端开50个线程的时候服务器Sleep(50),开100个现成的时候就得多Sleep一会),就不会再出现这个问题。

 

2012-06-27

 

名品推荐:伊贝诗 魅丝蔻 肌肤之钥

 

转载于:https://www.cnblogs.com/personnel/p/4583283.html

这个错误表明 Jenkins 在 Windows 环境下尝试执行 `sh` 命令失败,因为 Windows 默认没有 `sh`(Shell)解释器。以下是详细分析和解决方案: --- ### **错误原因** 1. **Windows 环境缺少 Shell** - Jenkins Pipeline 或脚本中调用了 `sh` 步骤(如 `sh 'echo hello'`),但 Windows 系统默认不提供 `sh.exe`。 - 错误中的 `CreateProcess error=2` 表示系统找不到 `sh` 可执行文件。 2. **路径问题** - 如果 Jenkins 配置了错误的 Shell 路径(如指向不存在的 `sh.exe`),也会触发此错误。 --- ### **解决方案** #### **1. 安装 Git for Windows(推荐)** - **步骤**: 1. 下载并安装 [Git for Windows](https://git-scm.com/downloads)。 2. 安装勾选 **"Use Git and optional Unix tools from the Command Prompt"**(将 `sh.exe` 等工具添加到系统路径)。 3. 重启 Jenkins 服务或服务器。 - **验证**: ```bash where sh # 在 CMD 中检查 sh.exe 路径(通常为 C:\Program Files\Git\bin\sh.exe) ``` #### **2. 修改 Jenkins 全局配置** 1. 进入 **Jenkins 管理 → 系统配置**。 2. 找到 **Shell 可执行文件** 设置: - 指定 `sh.exe` 的绝对路径(如 `C:\Program Files\Git\bin\sh.exe`)。 - 或直接填写 `bash.exe`(Git for Windows 提供的兼容层)。 #### **3. 在 Pipeline 中显式指定 Shell** 如果仅部分任务需要 `sh`,可以在 Pipeline 中指定: ```groovy pipeline { agent any stages { stage('Run Shell') { steps { // 方法1:使用 bat 执行 Windows 命令 bat 'echo Hello from CMD' // 方法2:显式调用 Git 的 sh.exe script { def shPath = '"C:\\Program Files\\Git\\bin\\sh.exe"' bat "${shPath} -c 'echo Hello from Shell'" } } } } } ``` #### **4. 使用 `bat` 替代 `sh`(纯 Windows 环境)** 如果不需要跨平台兼容性,直接使用 Windows 的 `bat` 步骤: ```groovy bat ''' echo 这是 Windows 命令 dir ''' ``` #### **5. 检查工作目录权限** 错误中提到的路径 `E:\JenkinsData\Jenkins\.jenkins\workspace\...` 可能存在以下问题: - 路径不存在或拼写错误。 - Jenkins 服务账户(如 `Local System`)无权限访问该目录。 **解决方法**: 1. 手动创建目录 `E:\JenkinsData\Jenkins\.jenkins\workspace`。 2. 确保 Jenkins 服务账户有读写权限(右键文件夹 → **属性 → 安全 → 编辑权限**)。 --- ### **调试技巧** 1. **在 Jenkins 脚本中打印环境变量**: ```groovy bat 'set' # 查看 PATH 和其他环境变量 ``` 2. **测试直接调用 `sh.exe`**: ```groovy bat '"C:\\Program Files\\Git\\bin\\sh.exe" --version' ``` --- ### **总结步骤** 1. **安装 Git for Windows** 并确保 `sh.exe` 在系统路径中。 2. **检查 Jenkins 全局 Shell 配置**(指向正确的 `sh.exe` 路径)。 3. **在 Pipeline 中区分 `sh` 和 `bat`**,或显式指定 Shell 路径。 4. **验证工作目录权限**,确保 Jenkins 可访问。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值