Socket編程實現客戶端與服務器一對一聊天
阿新 • • 發佈:2017-12-21
bug servers sys 編程 獲取 post edr class 一個
Socket(套接字)
使用Socket編程實現數據的交互需要經歷以下幾個步驟:
1、創建Socket:
Socket socket = new Socket("host",port);
2、打開IO流
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);//輸出流
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))//輸入流
註: socket屬於服務器,那麽socket的方法getOutputStream就是向客戶端輸出數據,getInputStream獲取客戶端傳過來的數據3、進行數據的交互
out.print() in.read();
4、關閉Socket
socket.close();
服務端跟客戶端有所不同,客戶端只要創建socket並且請求服務器連接connect,服務器創建完socket使用ServerSocket.accept()方法
阻塞程序直到收到了來自客戶端的請求,接收到來自客戶端的socket繼續往下執行。
其中客戶端代碼如下:
import java.net.*; import java.io.*; public class Client { boolean flag = false;//當遇到客戶端輸入bye取消與服務端連接的標識 public Client(){ try{ Socket socket =new Socket("127.0.0.1",4800);//(host,port) System.out.println("客戶端已經開啟----"); new Thread(new Output(socket)).start(); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));//獲取來自服務端的信息 String str = in.readLine();//讀取信息 while(!str.equals("bye")) { System.out.println("服務端:"+str); str = in.readLine();//當in每次調用readLine方法就會往下讀取一行,慎用 } in.close(); if (flag==true){ socket.close(); } } catch(Exception e){ e.printStackTrace(); } } //當客戶端沒有寫入信息的時候需要寫一個線程來實現寫操作,不然程序就會被卡在readLine一直獲取鍵盤信息 class Output implements Runnable{ Socket socket; public Output(Socket socket){ this.socket = socket; } public void run(){ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { PrintWriter out = new PrintWriter(socket.getOutputStream(),true); String str = br.readLine(); while(!str.equals("bye")) { System.out.println("客戶端:"+str); out.print(str+"\n");//從鍵盤沒有獲取到回車按鍵,需要加\n判斷一次輸入為一行 out.flush(); str = br.readLine(); if (str.equals("bye")) { flag = true; } } br.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { new Client(); } }
服務端代碼如下:
import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Server { boolean flag = false; public Server(){ try { ServerSocket serverSocket = new ServerSocket(4800); System.out.println("服務端正在等待客戶端請求......"); Socket socket = serverSocket.accept();//一直等待客戶端的請求 System.out.println("connect success"); new Thread(new Output(socket)).start(); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); /* int i = 0; while ((i = in.read()) != 0){ System.out.println(i); }*/ String str = in.readLine(); while(!str.equals("bye")) { System.out.println("客戶端:" + str); str = in.readLine(); } in.close(); if (flag==true) { socket.close(); serverSocket.close(); } } catch (IOException e) { e.printStackTrace(); } } class Output implements Runnable{ Socket socket; public Output(Socket socket){ this.socket = socket; } public void run(){ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { PrintWriter out = new PrintWriter(socket.getOutputStream(),true); String str = br.readLine(); while(!str.equals("bye")) { System.out.println("服務端:"+str); out.print(str+"\n"); out.flush(); str = br.readLine(); if (str.equals("bye")) { flag = true; } } br.close(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { new Server(); } }
總結
今天使用socket來實現客戶端與服務端的通信功能,遇到了很多問題,其中一個比較嚴重的就是沒有將寫操作放入線程中進行,導致程序沒有輸出信息,第二個問題是當獲取到從客戶端/服務端來的信息時候,我是一行行的進行讀取,但是沒有讀取到回車按鍵,無法區分一行的信息,導致客戶端輸入的信息,服務端無法接收,在朋友的debug下,使用了以下這個方法調試是否有數據傳到另一邊:
int i = 0; while ((i = in.read()) != 0){ System.out.println(i);
使用BufferReader的read方法返回的ASCII碼,強轉為int 可以直接獲取原來的值(在ASCII範圍內的值)。
Socket編程實現客戶端與服務器一對一聊天