fluent-logger-java is a Java library, to record events via Fluentd, from Java application. https://github.com/fluent/fluent-logger-java

使用该sdk过程发现,tcp连接断开之后,该sdk的重连机制无效。

2018-01-26 12:36:25,620 ERROR [org.fluentd.logger.sender.RawSocketSender] - <org.fluentd.logger.sender.RawSocketSender>
java.net.SocketException: Software caused connection abort: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:113)
at java.net.SocketOutputStream.write(SocketOutputStream.java:159)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at org.fluentd.logger.sender.RawSocketSender.flush(RawSocketSender.java:200)
at org.fluentd.logger.sender.RawSocketSender.send(RawSocketSender.java:188)
at org.fluentd.logger.sender.RawSocketSender.emit(RawSocketSender.java:158)
at org.fluentd.logger.sender.RawSocketSender.emit(RawSocketSender.java:140)
at org.fluentd.logger.sender.RawSocketSender.emit(RawSocketSender.java:135)
at org.fluentd.logger.FluentLogger.log(FluentLogger.java:101)
at org.fluentd.logger.FluentLogger.log(FluentLogger.java:86)
at fluentdDemo.fluentdDemo.main(fluentdDemo.java:90)

查看源码:见RawSocketSender类

private void reconnect() throws IOException {
if (socket == null) {
connect();
} else if (socket.isClosed() || (!socket.isConnected())) {
close();
connect();
}
}

判断 Socket 远程端连接如果关闭的话,就要重建连接。Socket的类提供了一些已经封装好的方法, 如  isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()等,

在测试时发现,这些方法都是本地端的状态,无法判断远端是否已经断开连接。

有些同学处理类似问题时,通过OutputStream发送一段测试数据,如果发送失败就表示远端已经断开连接,类似ping,但是这样会影响到正常的输出数据,远端无法把正常数据和测试数据分开。

其实,这种方法也是可以的,只不过,不要发送测试数据,直接发送需要发送的数据,一旦失败,就主动close socket,再新建连接,再重新发送就行了。

也有些同学想到通过发送紧急数据,来验证连接状态,见socket类(如下),如果失败,就close socket,再新建连接。

/**
* Send one byte of urgent data on the socket. The byte to be sent is the lowest eight
* bits of the data parameter. The urgent byte is
* sent after any preceding writes to the socket OutputStream
* and before any future writes to the OutputStream.
* @param data The byte of data to send
* @exception IOException if there is an error
* sending the data.
* @since 1.4
*/
public void sendUrgentData (int data) throws IOException {
if (!getImpl().supportsUrgentData ()) {
throw new SocketException ("Urgent data not supported");
}
getImpl().sendUrgentData (data);
}

可通过如下写法实现:

/**
* 判断是否断开连接,断开返回true,没有返回false
* @param socket
* @return
*/
public Boolean isServerClose(Socket socket){
try{
socket.sendUrgentData(0xFF);//发送1个字节的紧急数据,默认情况下,服务器端没有开启紧急数据处理,不影响正常通信
return false;
}catch(Exception se){
return true;
}
}

前提:对方Socket的SO_OOBINLINE属性没有打开,就会自动舍弃这个字节,而SO_OOBINLINE属性默认情况下就是关闭的

见SocketOptions接口

 /**
* When the OOBINLINE option is set, any TCP urgent data received on
* the socket will be received through the socket input stream.
* When the option is disabled (which is the default) urgent data
* is silently discarded.
*
* @see Socket#setOOBInline
* @see Socket#getOOBInline
*/
@Native public final static int SO_OOBINLINE = 0x1003;

当然,我觉得也可以通过定时发送紧急数据来做心跳,确保tcp长连接保活,对方可以不用回应。

测试结果:

这两种方式再连接断开后的第一次发送数据,并没有异常,但是server端没收到数据。第二次发送时候,才检测到连接异常。

有同学的说法是:Socket通过发送数据sendUrgentData()或PrintWriter 发送数据时的数据太小,被放到缓冲区没用实时发送导致的。后来尝试设置setSendBufferSize(1)发现能够正常出现异常,这样就能够判断实时网络连接断开了。(网上资料说sendUrgentData是实时发送数据不经过缓冲区的,但跟我实际测试的不一样,有待验证)

查看了一下源码,紧急数据的发送时间是,在之前write到OutputStream之后,在接下来write到OutputStream之前

 /**
* Send one byte of urgent data on the socket. The byte to be sent is the lowest eight
* bits of the data parameter. The urgent byte is
* sent after any preceding writes to the socket OutputStream
* and before any future writes to the OutputStream.
* @param data The byte of data to send
* @exception IOException if there is an error
* sending the data.
* @since 1.4
*/
public void sendUrgentData (int data) throws IOException {
if (!getImpl().supportsUrgentData ()) {
throw new SocketException ("Urgent data not supported");
}
getImpl().sendUrgentData (data);
}

  尝试设置setSendBufferSize(1)发现能够正常出现异常,这样就能够判断实时网络连接断开了。

fluentd的in_forward插件提供了基于udp的心跳监听,遗憾的是fluent-logger-java并没有做对应的心跳机制。

https://docs.fluentd.org/v0.12/articles/in_forward

  

  

socket 如何判断远端服务器的连接状态?连接断开,需重连的更多相关文章

  1. 利用LoadRunner判断HTTP服务器的返回状态

    利用LoadRunner判断HTTP服务器的返回状态第一种方法:是利用LR的内置函数web_get_int_property.举例:#include "web_api.h"Acti ...

  2. 通过psping测试结果,初步判断远端服务器的状态

    1.psping的输出结果为如下正常显示时,说明远端服务器的IP及端口可用 C:\Users\he.liming>psping 139.219.66.205:4352 PsPing v2.10 ...

  3. 怎样实时判断socket连接状态?

    对端正常close socket,或者进程退出(正常退出或崩溃),对端系统正常关闭 这种情况下,协议栈会走正常的关闭状态转移,使用epoll的话,一般要判断如下几个情况 处理可读事件时,在循环read ...

  4. C#通过socket判断FTP服务器是否通畅并判断用户名密码是否正确

    private static ManualResetEvent timeoutObject; private static Socket socket = null; private static b ...

  5. 系统编程-网络-tcp客户端服务器编程模型(续)、连接断开、获取连接状态场景

    相关博文: 系统编程-网络-tcp客户端服务器编程模型.socket.htons.inet_ntop等各API详解.使用telnet测试基本服务器功能 接着该上篇博文,咱们继续,首先,为了内容的完整性 ...

  6. loadrunner:判断是否服务器连接池瓶颈

    分析Web Resources中的Connections per second可以判断是否服务器连接池瓶颈. connections per second会给出两种不同状态的连接数:中断的连接和新建的 ...

  7. Linux中通过Socket文件描述符寻找连接状态介绍

    针对下文的总结:socket是一种文件描述符 进程的打开文件描述符表 Linux的三个系统调用:open,socket,pipe 返回的都是一个描述符.不同的进程中,他们返回的描述符可以相同.那么,在 ...

  8. [转]Linux服务器上11种网络连接状态 和 TCP三次握手/四次挥手详解

    一.Linux服务器上11种网络连接状态: 图:TCP的状态机 通常情况下:一个正常的TCP连接,都会有三个阶段:1.TCP三次握手;2.数据传送;3.TCP四次挥手. 注:以下说明最好能结合”图:T ...

  9. rtmp一些状态信息详解-as连接FMS服务器报错状态汇总~~

    原地址:http://help.adobe.com/zh_CN/AIR/1.5/jslr/flash/events/NetStatusEvent.html 下表说明了 code 和 level 属性可 ...

随机推荐

  1. 【转载】Sqlserver通过维护计划定时自动备份数据库

    Sqlserver数据库的运维过程中,数据库的备份操作至关重要,平时我们都是手动进行数据库的备份操作.如果要做到让数据库定时自动备份,则可以使用Microsoft SQL Server Managem ...

  2. 腾讯云图片鉴黄集成到C#

    官方文档:https://cloud.tencent.com/document/product/641/12422 请求官方API及签名的生成代码如下: var urlList = new List& ...

  3. c# 溢出上下文检测

    对于类型转换是否溢出可以用 checked和unchecked运算符 在unchecked上下文中会忽略溢出 在checked 会抛出异常 ; byte sb; sb = unchecked((byt ...

  4. 为什么redis是单线程的?速度还这么快

    为什么说Redis是单线程的? 为什么redis是单线程的?速度还这么快

  5. 【Java每日一题】20170208

    20170207问题解析请点击今日问题下方的“[Java每日一题]20170208”查看(问题解析在公众号首发,公众号ID:weknow619) package Feb2017; public cla ...

  6. 【转】为什么要使用ModelDriven

    ---恢复内容开始--- package cn.com.leadfar.struts2.actions; public class User { private int id ; private St ...

  7. 8.异常_EJ

    第57条: 只针对异常情况才使用异常 异常是为了在异常情况下使用而设计的,不要将它们用于普通的控制流,也不要编写迫使它们这么做的API. 第58条: 对可恢复的情况使用受检异常,对编程错误使用运行时异 ...

  8. jQuery插件之上传文件ajaxfileupload.js源码与使用

    在网页应用中,一般会用到上传文件或者图片什么的到服务器,那么可以用ajaxfileupload.js,但是在使用ajaxfileupload.js时候,当服务器返回的json带有&符号的时候, ...

  9. POJ 2942Knights of the Round Table(tarjan求点双+二分图染色)

    Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 13954   Accepted: 4673 Description Bein ...

  10. 洛谷P4590 [TJOI2018]游园会(状压dp LCS)

    题意 题目链接 Sol 这个题可能是TJOI2018唯一的非模板题了吧.. 考虑LCS的转移方程, \[f[i][j] = max(f[i - 1][j], f[i][j - 1], f[i - 1] ...