💤
💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨
💤
客戶端代碼
public class TcpEchoClient {
private String serverIp;
private int serverPort;
private Socket socket = null;
public TcpEchoClient(String serverIp, int serverPort) throws IOException {
this.serverIp = serverIp;
this.serverPort = serverPort;
// 讓socket創建的同時,就和服務器嘗試建立了連接
socket = new Socket(serverIp,serverPort);
}
public void start(){
Scanner scanner = new Scanner(System.in);
try(InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream()){
while(true){
// 1.從鍵盤上,讀取用戶的內容
System.out.println("-> ");
String request = scanner.nextLine();
if ("goodbye".equals(request)){
break;
}
// 2.把這個讀取的內容構成請求,發送給服務器
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.print(request);
// 3.從服務器讀取回應并決議
Scanner response = new Scanner(inputStream);
String responseStrings= response.next();
// 4.把結果顯示到界面上
String log = String.format("request: %s; response: %s",request,responseStrings);
System.out.println(log);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",8080);
tcpEchoClient.start();
}
}
服務器代碼
public class TcpEchoServer {
private ServerSocket serverSocket = null;
public TcpEchoServer(int port) throws IOException {
serverSocket = new ServerSocket(port);
}
public void start() throws IOException {
System.out.println("Server start!");
while(true){
// UDP的服務器進入主回圈,就直接嘗試receiver讀取請求了
// 但是TCP是有連接的,先要做的是,建立好連接
// 當服務器運行的時候,當前是否有客戶端來建立連接,不確定
// 如果客戶端沒有建立連接了,accept就會阻塞等待
// TODO: 2021/10/26 如果有多個客戶端對同一個服務器嘗試建立連接會發送什么?
// 如果有客戶端建立連接了,此時accept就會回傳一個socket物件
// 進一步的服務器和客戶端之間的互動,就交給client Socket
Socket clientSocket = serverSocket.accept();
processConnection(clientSocket);
}
}
private void processConnection(Socket clientSocket) throws IOException {
// 處理一個連接,在這個連接中可能會涉及客戶端和服務器之間的多次互動
String log = String.format("[%s:%d] 客戶端上線!",clientSocket.getInetAddress().toString(),
clientSocket.getPort());
System.out.println(log);
// 輸入
try(InputStream inputStream = clientSocket.getInputStream();
// 輸出
OutputStream outputStream = clientSocket.getOutputStream()) {
while (true) {
// 1.讀取請求并決議
// 可以直接通過 inputStream 的read 把資料讀到一個byte[]上,然后再轉成一個String
// 但是比較麻煩,還可以借助Scanner 來完成作業
Scanner scanner = new Scanner(inputStream);
if (!scanner.hasNext()){
log = String.format("[%s:%d] 客戶端下線",clientSocket.getInetAddress().toString(),
clientSocket.getPort());
System.out.println(log);
break;
}
String request = scanner.next();
System.out.println(request);
// 2.根據請求計算回應
String response = process(request);
// 3.把回應寫回給客戶端
PrintWriter writer = new PrintWriter(outputStream);
writer.print(response);
log = String.format("[%s:%d] req: %s; resp: %s",clientSocket.getInetAddress(),
clientSocket.getPort(),request,response);
System.out.println(log);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 當前的clientSocket生命周期,不是跟隨整個程式,而是和連接相關
// 因此就需要每個連接結束,都要進行關閉
// 否則隨著連接的增多,這個socket檔案就可能出現資源泄漏的情況
clientSocket.close();
}
}
private String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
TcpEchoServer tcpEchoServer = new TcpEchoServer(8080);
tcpEchoServer.start();
}
當我把服務器和客戶端啟動之后
Server start!
[/127.0.0.1:61497] 客戶端上線!
服務器和客戶端顯示正常運行
但客戶端發送請求后:
客戶端
->
AKA
服務器沒有做出任何的回應,這時候說明代碼中存在bug
猜測:
1.客戶端可能沒有正確的發送資料
2.服務器可能沒有正確讀取資料
回到代碼上
我們發送請求使用的是:
printWriter.print(request);
收取請求使用的是:
String request = scanner.next();
這里分析一些scanner.next()方法
next()在讀取到什么字符的時候才能回傳?
空白字符 如 空格、制表符、換行符、翻頁符
所以為了解決這個問題我們就需要才外加空白字符
方便起見,發送請求使用:
printWriter.println(request);
當修改完成后,再次運行
當我們在客戶端進行輸入的時候,發現服務器還是收不到客戶端的請求
這又是哪里出了問題???
回顧我們學習File和IO的時候,在寫資料的時候都會將資料先暫時寫入記憶體的一個指定區域里,直到該區域滿了或者其他指定條件時才真正將資料寫入設備中,這個區域一般稱為緩沖區,
因此我們的請求是不是被放到了緩沖區?
為了驗證一下
我們在發送請求的下面加上這一行代碼,用來重繪緩沖區
printWriter.print(request);
printWriter.flush();
再次運行
客戶端
->
AKA
request: AKA; response: AKA
服務器
Server start!
[/127.0.0.1:61835] 客戶端上線!
AKA
[/127.0.0.1:61835] req: AKA; resp: AKA
正常運行
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/340608.html
標籤:其他
