Java中利用socket实现简单的服务端与客户端的通信(中级)——实现任意双向通信
本文計(jì)劃采用socket實(shí)現(xiàn)客戶端和服務(wù)端的任意雙向通信,即客戶端可以隨時(shí)給服務(wù)端發(fā)消息,服務(wù)端也可以隨時(shí)給客戶端發(fā)消息,最終結(jié)果就是一個(gè)類似與QQ的聊天軟件的功能。
以下代碼可以直接拷貝到Eclipse中運(yùn)行。
前面的兩片文章都利用了socket實(shí)現(xiàn)了客戶端與服務(wù)器的通信,我的前兩片文章:
Java中利用socket實(shí)現(xiàn)簡單的服務(wù)端與客戶端的通信(入門級),實(shí)現(xiàn)了一個(gè)簡單的客戶端發(fā)送消息,服務(wù)器端接收消息的實(shí)力,沒有多線程,也沒有讓服務(wù)器端有消息返回。?
Java中利用socket實(shí)現(xiàn)簡單的服務(wù)端與客戶端的通信(基礎(chǔ)級),在上一篇的基礎(chǔ)上,在服務(wù)端實(shí)現(xiàn)了多線程,使得服務(wù)端可以于多個(gè)客戶端連接并接收他們發(fā)送的消息。
要想實(shí)現(xiàn)任意的雙向通信,以客戶端來說,時(shí)刻既需要能夠發(fā)送消息,同時(shí)也需要能夠隨時(shí)的接收服務(wù)端發(fā)來的消息,這兩個(gè)功能必須同時(shí)存在,還必須同時(shí)運(yùn)行,所以這個(gè)時(shí)候就必須使用到多線程了。無論是服務(wù)端還是客戶端,都至少需要多出兩個(gè)線程,一個(gè)線程用于發(fā)送數(shù)據(jù),一個(gè)線程用于接收數(shù)據(jù)。這是本文的關(guān)鍵。
客戶端:
package client_3;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; public class client_3 { public static final String IP = "localhost";//服務(wù)器地址 public static final int PORT = 10000;//服務(wù)器端口號 public static void main(String[] args) {handler(); } private static void handler(){ try { //實(shí)例化一個(gè)Socket,并指定服務(wù)器地址和端口 Socket client = new Socket(IP, PORT); System.out.println("I am a client"); //開啟兩個(gè)線程,一個(gè)負(fù)責(zé)讀,一個(gè)負(fù)責(zé)寫 new Thread(new ReadHandlerThread(client)).start(); new Thread(new WriteHandlerThread(client)).start(); } catch (Exception e) { e.printStackTrace(); } } } /* *處理讀操作的線程 */ class ReadHandlerThread implements Runnable{ private Socket client; public ReadHandlerThread(Socket client) { this.client = client; } @Override public void run() { BufferedReader in = null;try {in = new BufferedReader(new InputStreamReader(client.getInputStream()));} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}try { while(true){ System.out.println("服務(wù)器說:"+in.readLine()); } } catch (IOException e) { e.printStackTrace(); } finally{ if(client != null){ client = null; } } } } /* * 處理寫操作的線程 */ class WriteHandlerThread implements Runnable{ private Socket client; public WriteHandlerThread(Socket client) { this.client = client; } @Override public void run() { PrintWriter out=null;try {out = new PrintWriter(client.getOutputStream());} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));//從控制臺獲取輸入的內(nèi)容 try { while(true){ out.println(reader.readLine()); out.flush();} } catch (IOException e) { e.printStackTrace(); }try {client.close();reader.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}out.close();} } 可以看到,上述代碼有兩個(gè)線程類,一個(gè)負(fù)責(zé)讀,一個(gè)負(fù)責(zé)寫,同樣的,服務(wù)端的代碼也大同小異。
服務(wù)端:
package server_3;import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; public class server_3 { public static final int PORT = 10000;//監(jiān)聽的端口號 public static void main(String[] args) { System.out.println("sever begins");server_3 server = new server_3(); server.init(); } public void init() { ServerSocket serverSocket = null; try { serverSocket = new ServerSocket(PORT); while (true) { Socket client = serverSocket.accept(); //一個(gè)客戶端連接就開兩個(gè)線程分別處理讀和寫 new Thread(new ReadHandlerThread(client)).start(); new Thread(new WriteHandlerThread(client)).start(); } } catch (Exception e) { e.printStackTrace(); } finally{ try { if(serverSocket != null){ serverSocket.close(); } } catch (IOException e) { e.printStackTrace(); } } } } /* *處理讀操作的線程 */ class ReadHandlerThread implements Runnable{ private Socket client=null; public ReadHandlerThread(Socket client) { this.client = client; } @Override public void run() { BufferedReader in = null;try{ while(true){ //讀取客戶端數(shù)據(jù) in = new BufferedReader(new InputStreamReader(client.getInputStream()));System.out.println("客戶端說:" + in.readLine()); } }catch(Exception e){ e.printStackTrace(); }finally{ if(client != null){ client = null; } } } } /* * 處理寫操作的線程 */ class WriteHandlerThread implements Runnable{ private Socket client; public WriteHandlerThread(Socket client) { this.client = client; } @Override public void run() { PrintWriter out=null;try {out = new PrintWriter(client.getOutputStream());} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();} BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));//從控制臺獲取輸入的內(nèi)容 try{ while(true){ //向客戶端回復(fù)信息 out.println(reader.readLine());out.flush(); } }catch(Exception e){ e.printStackTrace(); }finally{ if(client != null){ client = null; } } } }以上程序,先啟動(dòng)服務(wù)端,再啟動(dòng)客戶端,就可以實(shí)現(xiàn)兩端的任意聊天,功能和qq等軟件類似。
總結(jié)
以上是生活随笔為你收集整理的Java中利用socket实现简单的服务端与客户端的通信(中级)——实现任意双向通信的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中利用socket实现简单的服务
- 下一篇: Java编译型语言还是解释型语言