网络重启、已连接端口掐灭可自动重连。
Java实现的Demo代码如下:
package top.onefine.test;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* 发送模拟数据,可以自动重连
*
* @author one fine<br/>
*/
public class SendImitateData {
public static final String HOST_ = "127.0.0.1";
public static final int PORT_ = 11222;
public static final int TIME_OUT = 30 * 1000;
public static void main(String[] args) throws InterruptedException {
Socket socket;
while (true) {
CyclicBarrier barr = new CyclicBarrier(3);
System.out.println("connecting to Server " + HOST_ + ":" + PORT_);
socket = initSocket();
if (socket != null && socket.isConnected() && !socket.isClosed()) {
System.out.println("connected...");
OutThread out = new OutThread(barr, socket);
out.start();
InThread in = new InThread(barr, socket);
in.start();
try {
barr.await(); // 第一次,等着
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("connected failed, sleep for 10 s!");
Thread.sleep(10 * 1000);
}
barr.reset(); // 重置
}
}
private static Socket initSocket() {
Socket socket;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(HOST_, PORT_), TIME_OUT);
} catch (IOException e) {
return null;
}
return socket;
}
}
class OutThread extends Thread {
private Socket socket;
private CyclicBarrier barr;
public OutThread(CyclicBarrier barr, Socket socket) {
this.barr = barr;
this.socket = socket;
}
@Override
public void run() {
boolean target = true;
BufferedOutputStream bos = null;
while (target) {
try {
assert socket != null;
if (socket.isConnected() && !socket.isClosed()) {
bos = getBufferedOutputStream(socket);
assert bos != null;
bos.write(getCommandBytes());
bos.write(new byte[]{
0x0d, 0x0a});
bos.flush();
} else {
target = false;
}
Thread.sleep(1000 * 10);
} catch (Exception e) {
System.out.println("OutThread = " + e.getMessage());
target = false;
} finally {
try {
if (bos != null) {
bos.close();
}
if (socket != null) {
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
try {
barr.await(); // 第二次,等着
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
private static BufferedOutputStream getBufferedOutputStream(Socket socket) {
try {
return new BufferedOutputStream(socket.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
private static byte[] getCommandBytes() {
StringBuilder command = new StringBuilder("##00000");
command.append(";A0=").append(getRandomFloat());
command.append(";A1=").append(getRandomFloat());
command.append(";B0=").append(getRandomFloat());
command.append(";C0=").append(getRandomFloat());
command.append(";C1=").append(getRandomFloat());
command.append(";C2=").append(getRandomFloat());
command.append(";C3=").append(getRandomFloat());
System.out.println(command.toString());
return command.toString().getBytes();
}
private static Float getRandomFloat() {
Random random = new Random();
return BigDecimal.valueOf(random.nextDouble() * 100).setScale(2, RoundingMode.UP).floatValue();
}
}
class InThread extends Thread {
private Socket socket;
private CyclicBarrier barr;
public InThread(CyclicBarrier barr, Socket socket) {
this.barr = barr;
this.socket = socket;
}
@Override
public void run() {
boolean target = true;
BufferedInputStream bis = null;
while (target) {
try {
assert socket != null;
if (socket.isConnected() && !socket.isClosed()) {
bis = getBufferedInputStream(socket);
byte[] tmp = new byte[1024];
int re;
while ((re = bis.read(tmp)) != -1) {
System.out.println(new String(tmp, 0, re));
}
} else {
target = false;
}
Thread.sleep(1000 * 10);
} catch (Exception e) {
System.out.println("InThread = " + e.getMessage());
target = false;
} finally {
try {
if (bis != null) {
bis.close();
}
if (socket != null) {
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
try {
barr.await(); // 第三次,等着
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
private static BufferedInputStream getBufferedInputStream(Socket socket) {
try {
return new BufferedInputStream(socket.getInputStream());
} catch (IOException e) {
return null;
}
}
}
这里CyclicBarrier的详细使用详文末参考!这里简单提一下:
CyclicBarrier字面的中文意思是“循环栅栏[zhà lan]”,大概的意思就是一个可循环利用的屏障。它的作用就是会让所有线程都等待完成后才会继续下一步行动。
简化:
package top.onefine.test;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* @author one fine<br/>
*/
public class TCPDemo {
public static final String HOST = "127.0.0.1";
public static final int PORT = 11222;
public static final int TIME_OUT = 30 * 1000;
public static void main(String[] args) throws Exception {
Socket socket;
while (true) {
CyclicBarrier barr = new CyclicBarrier(2);
System.out.println("connecting to Server " + HOST + ":" + PORT);
socket = initSocket();
if (socket != null && socket.isConnected() && !socket.isClosed()) {
System.out.println("connected...");
InThread1 in = new InThread1(barr, socket);
in.start();
try {
barr.await(); // 第一次,等着
} catch (Exception e) {
e.printStackTrace();
}
} else {
System.out.println("connected failed, sleep for 10 s!");
Thread.sleep(10 * 1000);
}
barr.reset(); // 重置
}
}
private static Socket initSocket() {
Socket socket;
try {
socket = new Socket();
socket.connect(new InetSocketAddress(HOST, PORT), TIME_OUT);
} catch (IOException e) {
e.printStackTrace(); // java.net.ConnectException: Connection refused: connect
return null;
}
return socket;
}
}
class InThread1 extends Thread {
private Socket socket;
private CyclicBarrier barr;
public InThread1(CyclicBarrier barr, Socket socket) {
this.barr = barr;
this.socket = socket;
}
@Override
public void run() {
boolean target = true;
BufferedInputStream bis = null;
while (target) {
try {
assert socket != null;
if (socket.isConnected() && !socket.isClosed()) {
bis = getBufferedInputStream(socket);
byte[] tmp = new byte[1024];
int re;
while ((re = bis.read(tmp)) != -1) {
System.out.println(new String(tmp, 0, re));
}
} else {
target = false;
System.out.println("连接断开...");
}
Thread.sleep(1000 * 10);
} catch (Exception e) {
System.out.println("InThread = " + e.getMessage());
target = false;
} finally {
try {
if (bis != null) {
bis.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
try {
barr.await(); // 第二次,等着
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
private static BufferedInputStream getBufferedInputStream(Socket socket) {
try {
return new BufferedInputStream(socket.getInputStream());
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
注意:
在socket类中有一个方法sendUrgentData,它会往输出流发送一个字节的数据,只要对方Socket的SO_OOBINLINE属性没有打开,就会自动舍弃这个字节(在Java 中是抛出异常),而SO_OOBINLINE属性默认情况下就是关闭的。
参考:
深入理解CyclicBarrier原理 https://blog.csdn.net/qq_39241239/article/details/87030142
CyclicBarrier 使用详解 https://www.jianshu.com/p/333fd8faa56e
JAVA 判断Socket 远程端是否断开连接 https://www.cnblogs.com/wisdo/p/5859857.html