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)