JAVA套接字實現簡易的雙人通訊系統
阿新 • • 發佈:2020-12-30
JAVA套接字實現簡易的雙人通訊系統
JAVA套接字資料
socket是基於應用服務與TCP/IP通訊之間的一個抽象,他將TCP/IP協議裡面複雜的通訊邏輯進行分裝,對使用者來說,只要通過一組簡單的API就可以實現網路的連線。借用網路上一組socket通訊圖給大家進行詳細講解:
首先,服務端初始化ServerSocket,然後對指定的埠進行繫結,接著對埠及進行監聽,通過呼叫accept方法阻塞,此時,如果客戶端有一個socket連線到服務端,那麼服務端通過監聽和accept方法可以與客戶端進行連線。
以上資料:
作者:長道
連結:https://www.jianshu.com/p/cde27461c226
來源:簡書
解決方案
綜上所述,JAVA套接字需要一個SeverSocket物件作為服務端,監聽Socket的連線請求,需要一個Socket物件作為客戶端,向SeverSocket傳送連線的請求。客戶端和服務端建立連線後為全雙工,兩端均可接收和傳送資料,接收和傳送均可用流來實現。但是若兩端僅僅用while迴圈來不停的傳送和接受資料會發生阻塞,也就是說只有一端完成傳送操作後,才能開始接受操作,而鍵盤讀取字串的函式是阻塞的,sock流的讀寫也會發生阻塞,只有輸入並按下回車才會繼續執行,另一端也相同。最終造成的結果是兩端分別每次只能說一句話,只有對方發來資訊後,才可也說下一句。解決方法就是利用多執行緒,服務端和客戶端都設定兩個執行緒,一個執行緒專門用來接受資訊,一個專門用來發送資訊。這樣,接收和傳送互不影響,消除阻塞。
主要程式碼塊
服務端,接收客戶端的連線請求,建立新的執行緒:
客戶端,請求連線,並建立新的執行緒:
接收的執行緒:不斷從輸入流讀取資料並列印
傳送的執行緒:不斷從鍵盤讀取字串並寫入輸出流
客戶端和服務端的接收和傳送程序基本相同
執行結果
最終程式碼
服務端
package com; import java.io.IOException; import java.io.*; import java.net.*; import java.util.Scanner; public class Server{ static ServerSocket serverSocket; public static void main(String[] args) { try { serverSocket = new ServerSocket(1515); while(true) { Socket accept_client = serverSocket.accept(); new Thread(new ServerIn(accept_client)).start(); new Thread(new ServerOut(accept_client)).start(); } } catch (IOException e) { e.printStackTrace(); try { serverSocket.close(); } catch (IOException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } } } } //接受的執行緒 class ServerIn implements Runnable{ Socket socket; ServerIn(Socket socket){ this.socket = socket; } @Override public void run() { try { InputStream in = socket.getInputStream(); while(true) { byte infile[] = new byte[1024]; int size = in.read(infile); String string = new String(infile,0,size); if(!string.equals("") && !string.equals("\n")) System.out.println("message from client: "+ string); } } catch (IOException e) { e.printStackTrace(); try { socket.close(); } catch (IOException e1) { e1.printStackTrace(); } } } } //傳送的執行緒 class ServerOut implements Runnable{ Socket socket; Scanner reader = new Scanner(System.in); ServerOut(Socket socket){ this.socket = socket; } public void run() { try { OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream()); while(true) { String string = reader.nextLine(); out.write(string); out.flush(); } } catch (IOException e) { e.printStackTrace(); try { socket.close(); reader.close(); } catch (IOException e1) { e1.printStackTrace(); } } } }
客戶端
package com;
import java.io.*;
import java.util.*;
import java.net.*;
public class Client{
public static void main(String[] args) {
try {
Socket client = new Socket("127.0.0.1",1515);
new Thread(new ClientIn(client)).start();
new Thread(new ClientOut(client)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//接受的執行緒
class ClientIn implements Runnable{
Socket socket;
ClientIn(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
InputStream in = socket.getInputStream();
while(true) {
byte infile[] = new byte[1024];
int size = in.read(infile);
String string = new String(infile,0,size);
if(!string.equals("") && !string.equals("\n")) System.out.println("message from server: "+ string);
}
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
//傳送的執行緒
class ClientOut implements Runnable{
Socket socket;
Scanner reader = new Scanner(System.in);
ClientOut(Socket socket){
this.socket = socket;
}
public void run() {
try {
OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
while(true) {
String string = reader.nextLine();
out.write(string);
out.flush();
}
} catch (IOException e) {
e.printStackTrace();
try {
socket.close();
reader.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
}
計算1913 李文軒