TCP 长连接小尝试,demo
本文学习了这两天看了不少tcp的使用细节,也看了不少有用的前辈经验,这里只是简单总结一下,有些奇怪的地方,BufferedReader,sendUrgentData。
- 面临的问题是:写一个第三方程序信息接收服务器,协议上完全被动,等待连接接收消息。
服务端主要逻辑更新
堵塞的(BufferedReader)读取每条信息
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
try {
// 获取一个输入流,接收服务端的信息
inputStream = (InputStream) socket.getInputStream();
// 包装成字符流,提高效率,如果有乱码问题
inputStreamReader = new InputStreamReader(inputStream, "xxx");
bufferedReader = new BufferedReader(inputStreamReader);
char[] rcchar = new char[REVEIVEBUFFERSIZE];
while (run) {//长连接读取远程信息,当连接断开会抛出异常
int len = bufferedReader.read(rcchar);
if(len==-1){//连接中断,,,
throw new Exception("read socket err");
}
String crtstr = String.valueOf(rcchar, 0, len);
System.out.println(new Date() + " : " + crtstr);
}
} catch (Exception e) {
//与客户端连接中断
try {
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
socket.close();
} catch (IOException e1) {
}
}
服务端主要逻辑
当serversocket接收到连接时,开启一个线程服务,非堵塞读取
class XXXConnect extends Thread {
// 定义系统信息接收延迟:一秒
private static final int receiveDelayMS = 1000;
// 接收缓存8k,可能含多条数据,粘包等等。
private static final int REVEIVEBUFFERSIZE = 1024 * 8;
private Socket socket;
private InputStream in;
private boolean run = true;
private byte[] receiveData = new byte[REVEIVEBUFFERSIZE];
public XXXConnect(Socket socket) {
this.socket = socket;
try {
in = socket.getInputStream();
} catch (IOException e) {
run = false;
try {
socket.close();
} catch (IOException e1) {
}
}
}
@Override
public void run() {
try {
while (run) {
// 从远程读取数据时,远程连接断开将抛出异常
//(Software caused connection abort: recv failed)
int len = in.read(receiveData, 0, REVEIVEBUFFERSIZE);
if (len != -1) {
System.out.println(new Date()
+ "receive:" + new String(receiveData, 0, len));
}
Thread.sleep(receiveDelayMS);
// 测试:异常表明远程连接断开:Connection reset by peer: send
// 发送任意数据:测试连接是否正常(心跳)
socket.sendUrgentData(0xFF);
}
socket.close();
} catch (Exception e) {
}
}
}
客户端发送测试
多次发送数据,然后服务端接收
// 创建Socket对象
Socket socket = new Socket("127.0.0.1", 11101);
// 根据输入输出流和服务端连接
OutputStream outputStream = (OutputStream) socket.getOutputStream();// 获取一个输出流,向服务端发送信息
PrintWriter printWriter = new PrintWriter(outputStream);// 将输出流包装成打印流
int ccc = 40;
while (ccc > 0) {
//Thread.sleep(1200);
printWriter.print("服务端你ashfgehjsfbehjdsfbsjffj219278 27 3 好,我是Balla_兔子");
printWriter.flush();
ccc--;
}
Thread.sleep(10000);//等待那边服务器接收玩消息退出,
System.out.println("bye server");
printWriter.close();
outputStream.close();
socket.close();
这些写完后,发现了一个问题发送sendUrgentData 影响对方的报文接收。
int ccc = 30;
while (ccc > 0) {
socket.sendUrgentData(0xFF);
printWriter.print(ccc + "服务端你ashfgehjsfbehjdsfbsjffj219278 27 3 好,我是Balla_兔子");
printWriter.flush();
//Thread.sleep(3000);
ccc--;
}
- windows下,如果A给B,发送一段报文,同时也发送多次socket.sendUrgentData(0xFF) ,B接收到的报文会缺失部分。
我又试了试linux下,如果A给B,发送一段报文,同时也发送多次socket.sendUrgentData(0xFF) ,A接收到的报文会混入未知字符。
Microsoft Windows [版本 10.0.14393]
java version “1.8.0_91”
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)Linux 4.10.6-200.fc25.x86_64 #1 SMP Mon Mar 27 14:06:23 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
java version “1.8.0_111”
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)