java socket 断开连接,检查ClientSocket是否在java中断开连接

This is a follow up to:

Basically, I have a server loop that manages a connection to one solitary client. At one point in the loop, if a ClientSocket exists it attempts a read to check if the client is still connected:

if (bufferedReader.read()==-1 ) {

logger.info("CONNECTION TERMINATED!");

clientSocket.close();

setUpSocket(); //sets up the server to reconnect to the client

}else{

sendHeartBeat(); //Send a heartbeat to the client

}

The problem is, that once a socket has been created the application will hang on the read, I assume waiting for data that will never come, since the client never sends to the server. Before this was OK, because this correctly handled disconnects (the read would eventually fail when the client disconnected) and the loop would attempt reestablish the connection. However, I now have added the above sendHeartBeat() method, which periodically lets the client know the server is still up. If the read is holding the thread then the heartbeats never happen!

So, I assume I am testing if the connection is still up incorrectly. I could, as a quick hack, run the bufferedReader.read() in a seperate thread, but then I'll have all sorts of concurrency issues that I really don't want to deal with.

So the question is a few fold:

1) Am I checking for a client disconnect correctly?

2) If not, how should I do it?

3) If I am doing it correctly how I do I get the read to not hold the process hostage? Or is threading the only way?

解决方案

When you create your socket, first set a timeout:

private int timeout = 10000;

private int maxTimeout = 25000;

clientSocket.setSoTimeout(timeout);

With this, if a read times out you'll get java.net.SocketTimeoutException (which you have to catch). Thus, you could do something like this, assuming you've previously set the SO_TIMEOUT as shown above, and assuming that the heartbeat will always get a response from the remote system:

volatile long lastReadTime;

try {

bufferedReader.read();

lastReadTime = System.currentTimeMillis();

} catch (SocketTimeoutException e) {

if (!isConnectionAlive()) {

logger.info("CONNECTION TERMINATED!");

clientSocket.close();

setUpSocket(); //sets up the server to reconnect to the client

} else {

sendHeartBeat(); //Send a heartbeat to the client

}

}

public boolean isConnectionAlive() {

return System.currentTimeMillis() - lastReadTime < maxTimeout;

}

A common way of handling this is setting the timeout to some number (say 10 seconds) and then keeping track of the last time you successfully read from the socket. If 2.5 times your timeout have elapsed, then give up on the client and close the socket (thus sending a FIN packet to the other side, just in case).

If the heartbeat will not get any response from the remote system, but is just a way of ultimately generating an IOException earlier when the connection has fallen down, then you could do this (assuming that the sendHeartBeat itself will not throw an IOException):

try {

if (bufferedReader.read() == -1) {

logger.info("CONNECTION TERMINATED with EOF!");

resetConnection();

}

} catch (SocketTimeoutException e) {

// This just means our read timed out ... the socket is still good

sendHeartBeat(); //Send a heartbeat to the client

} catch (IOException e) {

logger.info("CONNECTION TERMINATED with Exception " + e.getMessage());

resetConnection();

}

....

private void resetConnection() {

clientSocket.close();

setUpSocket(); //sets up the server to reconnect to the client

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
请注意,UDP是无连接的传输协议,因此不能像TCP一样保持长连接。UDP套接字可以连续发送和接收数据包,但无法保证它们的顺序或到达的时间。 以下是一个使用Java UDP套接字进行数据传输的示例代码: 客户端: ```java import java.net.*; public class UDPClient { public static void main(String args[]) throws Exception { DatagramSocket clientSocket = new DatagramSocket(); InetAddress IPAddress = InetAddress.getByName("localhost"); byte[] sendData; byte[] receiveData = new byte[1024]; String sentence = "Hello Server!"; sendData = sentence.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876); clientSocket.send(sendPacket); DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); clientSocket.receive(receivePacket); String modifiedSentence = new String(receivePacket.getData()); System.out.println("FROM SERVER:" + modifiedSentence); clientSocket.close(); } } ``` 服务器: ```java import java.net.*; public class UDPServer { public static void main(String args[]) throws Exception { DatagramSocket serverSocket = new DatagramSocket(9876); byte[] receiveData = new byte[1024]; byte[] sendData; while (true) { DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length); serverSocket.receive(receivePacket); String sentence = new String(receivePacket.getData()); InetAddress IPAddress = receivePacket.getAddress(); int port = receivePacket.getPort(); String capitalizedSentence = sentence.toUpperCase(); sendData = capitalizedSentence.getBytes(); DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, port); serverSocket.send(sendPacket); } } } ``` 这个示例演示了一次简单的UDP数据包发送和接收。您可以将其扩展为在多个数据包之间保持连接并以长连接形式运行。但请注意,UDP套接字不能保证传输的可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值