程序异常:Connection reset by peer

本文分享了一种解决在Linux环境下预生产和生产环境中遇到的Oracle数据库连接异常问题的方法。通过修改JDK安装目录下的java.security文件,将dev/random替换为dev/urandom,成功解决了Connectionresetbypeer异常,确保了应用程序能够稳定地访问数据库。

一、前言

最近项目上线遇到一个bug,说一下背景,项目分为开发、测试、预生产和生产,要连接的oracle数据库地址也就不同了,jar包运行的环境也不同,开发和测试环境都是在本地进行的,所以连接的数据库也没问题。但是程序移植到预生产和生产环境的时候就出现问题了,就是在程序启动的时候连接oracle的时候,预生产环境会在第一次连接失败,然后等到有请求进来的时候,重新去创建连接就可以连接成功。生产环境权限比较高,所以不能直接将程序跑起来测试生产环境是否可以连接生产oracle数据库,只能是写一个简单的demo去测试连接,其他的什么都不能干。生产环境测试连接生产oracle数据库,一直报异常Connection reset by peer,一开始以为是权限问题,后来弄来了有权限的用户名和密码,demo依然报上面的异常。还有一点是生产环境是Linux系统,这和这个问题起因有关。

二、解决办法(先上解决办法)

修改程序运行系统中安装的jdk文件,找到你安装jdk的安装目录,自己安哪就找哪,然后修改 JAVA_HOME/jre/lib/security/java.security 文件,JAVA_HOME代表你的***JDK***安装目录,看好是***JDK***。
打开后(如果打不开,下载个notepad++)找到文件中的 dev/random 修改为 dev/urandom 这个文件挺长的,就不贴了。
修改完成后上传demo就能够正常访问数据库了。

三、其他情况

像数据库断断续续连不上,或者达成war包放到tomcat里面,执行 startup.sh老是卡住了等情况。这个问题貌似也可以修改oracle的配置,但是生产的数据库已经运行了好几年了,是没有权利去修改的。。。
四、 其他博客和java.security.SecureRandom源码分析链接
1)tomcat的https://www.cnblogs.com/greys/p/10722950.html
2)外文的 https://answers.splunk.com/answers/710452/db-connect-javasqlsqlrecoverableexception-io-error.html
3)阿里云栖的:https://yq.aliyun.com/articles/714374
4)源码分析:https://blog.51cto.com/leo01/1795447

你遇到的错误信息: ``` recv head error: Connection reset by peer ``` 是网络编程中常见的一种错误,表示**对端(peer)已经关闭了连接,而本端仍在尝试接收数据(recv)**。 --- ## ✅ 错误含义详解 | 错误信息 | 含义 | |----------|------| | `recv` | 系统调用或 socket API 用于接收数据 | | `Connection reset by peer` | 对端(客户端或服务端)异常关闭了连接,导致本端的 socket 收到 RST(Reset)标志 | --- ## ✅ 出现原因 ### 1. 对端提前关闭了连接 例如: - 客户端发送完请求后立即断开连接; - 服务端处理完响应后关闭了连接; - 对端程序异常退出; - 对端主动发送了 `RST` 包(如调用 `close()` 或 `shutdown()`)。 ### 2. 本端在连接关闭后仍尝试读取数据 ```c char buffer[1024]; int bytes = recv(sockfd, buffer, sizeof(buffer), 0); if (bytes == 0) { printf("Connection closed by peer\n"); } else if (bytes < 0) { perror("recv failed"); } ``` 如果此时连接已被对端关闭,`recv()` 会返回 `0`(表示 EOF)或 `-1` 并设置 `errno = ECONNRESET`。 --- ## ✅ C 语言中如何处理这个错误 ### ✅ 示例代码(TCP 接收数据) ```c #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdio.h> #include <string.h> #include <errno.h> void handle_client(int client_fd) { char buffer[1024]; int bytes_read; while ((bytes_read = recv(client_fd, buffer, sizeof(buffer), 0)) > 0) { // 正常处理数据 printf("Received %d bytes\n", bytes_read); } if (bytes_read == 0) { printf("Connection closed by peer\n"); } else if (bytes_read == -1) { if (errno == ECONNRESET) { printf("Connection reset by peer\n"); } else { perror("recv error"); } } close(client_fd); } ``` --- ## ✅ Python 中如何处理这个错误 如果你是在 Python 中使用 socket 编程,也可以捕获这个错误: ```python import socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(('example.com', 80)) try: data = sock.recv(4096) if not data: print("Connection closed by peer") print("Received data:", data) except socket.error as e: if e.errno == 104: # Connection reset by peer print("Connection reset by peer") else: print("Socket error:", e) finally: sock.close() ``` --- ## ✅ 如何避免或处理这个问题 | 方法 | 说明 | |------|------| | ✅ 正确处理 `recv()` 返回值 | 返回 `0` 表示连接关闭,返回 `-1` 并检查 `errno` | | ✅ 使用 `select()` 或 `poll()` | 在读取前检查 socket 是否可读 | | ✅ 设置 socket 选项 `SO_KEEPALIVE` | 自动检测连接是否存活 | | ✅ 设置 `SIGPIPE` 忽略 | 避免写入已关闭的 socket 导致崩溃 | | ✅ 对连接进行重连机制 | 如果是客户端,可尝试重新连接服务端 | | ✅ 使用心跳机制 | 定期发送心跳包检测连接是否有效 | --- ## ✅ 总结 - `Connection reset by peer` 表示对端异常关闭了连接; - `recv()` 返回 `0` 表示正常关闭,返回 `-1` 且 `errno == ECONNRESET` 表示异常关闭; - 不管是 C 还是 Python,都应该正确处理 socket 关闭的情况; - 在网络编程中,这种错误是正常现象,应做好错误处理和连接管理。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喵喵@香菜

感谢观众老爷送的一发火箭!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值