點我跳過黑哥的卑鄙廣告行爲,進入正文。html
Java多線程系列更新中~java
正式篇:編程
番外篇(神TM番外篇):服務器
Socket是客戶端和服務器端交流的端點。經過它能夠實現客戶端和服務器端的通訊。順着這篇文章操做下來,你應該會對Socket編程有比較系統的瞭解。注意,跟着敲代碼,有什麼不懂而我又沒提到的地方,隨時百度,不要積累偏差。網絡
Socket是有鏈接的,因此雙方創建通訊,須要知道彼此的網絡位置(IP和端口)。多線程
建立Socket對象:socket
Socket socket = new Socket("127.0.0.1",8852);
爲何須要端口號?例如你想要去找你的暗戀對象告白,你知道她的學校地址(IP地址),可是一個學校不會只有你暗戀對象一我的(一個主機不會只進行一個任務),你須要知道她的宿舍號(端口號),這樣才能方便告白。ide
使用本機既作客戶端,又作服務器是個什麼狀況?就是你和你暗戀對象在同一個學校,這沒什麼區別,你仍然須要她的宿舍號(端口號)才能找到她告白(客戶端和服務前通訊)。函數
public class MyClient { public static void main(String[] args) throws Exception{ Socket socket = new Socket("127.0.0.1",8852); DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); dataOutputStream.writeUTF("Hello socket"); socket.close(); } }
注意別忘了拋出異常,這裏只是個演示做用,直接throws Exception了。這裏你直接運行確定是不能創建鏈接的,由於服務器端還沒寫。spa
這裏,假如你知道服務器監聽的是8852端口,你建立了一個socket來和它進行通訊。socket.getOutputStream()獲得這個socket的輸出流,當你調用writeUTF()方法時,便會向其中寫一個字符串。
典型三段式要牢記:打開、通訊、關閉。
注意了注意了,要開始造女票了。
import java.io.DataInputStream; import java.net.ServerSocket; import java.net.Socket; public class MyServer { public static void main(String[] args) throws Exception{ ServerSocket serverSocket = new ServerSocket(8852); System.out.println("Server 等待接收數據~"); Socket socket = serverSocket.accept(); DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); String string = dataInputStream.readUTF(); System.out.println(string); System.out.println("Server 接收數據完畢,拜拜了您~"); socket.close(); serverSocket.close(); } }
這裏服務器端用到了ServerSocket,負責接收客戶端的鏈接請求。你的暗戀對象可能有好多人要向她告白,一個Socket天然沒法處理。經過ServerSocket的accept方法從鏈接請求隊列中取出一個進行鏈接。那這個ServerSocket就是你暗戀對象的室友,幫助她管理諸多「告白」。
這裏只是把服務器端接收到的數據打印了一下便關閉了。至此,一個簡單的服務器-客戶端通訊便創建了。可是這個服務器只能處理一個鏈接便關閉了,咱們能夠改進一下。
往下看以前請確保你大體理解了上述過程,最好本身敲一下代碼
到這裏你可能會想,只處理一個就關閉了,那我加個while循環,讓它一直運行怎麼樣?
聽着還能夠,那咱們來試驗一下(下面只是分析一下,不用跟着敲)。
將服務器端代碼更改成:
while(true) { Socket socket = serverSocket.accept(); DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); String string = dataInputStream.readUTF(); System.out.println(string); socket.close(); serverSocket.close(); }
這個會出現什麼問題?客戶端正連着呢,啪,你服務器給人家斷開了,並且accept()接受的是socket請求,因此這種狀況,除非客戶端再連一次,不然兩者的通訊就斷了。
你可能會說,那我把Socket移到外面呢?
其實吧,這個仔細理一下就會明白,若是放到外面的話,只要你想接收多個socket,就要把
Socket socket = serverSocket.accept();放到while循環中,可是你只要把它放到while循環中,它就只能和一個socket進行通訊。這裏有興趣能夠再查閱一下資料,下面直接進入線程階段。
import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class MyServer { public static void main(String[] args) throws Exception{ ServerSocket serverSocket = new ServerSocket(8852); System.out.println("Server 等待接收數據~"); while(true) { Socket socket = serverSocket.accept();
//這裏來一個鏈接請求就讓deal去處理,本身在這裏等下一個鏈接請求 deal(socket); } } public static void deal(Socket client){
//這裏建立了一個新的線程 new Thread(new Runnable() { @Override public void run() { DataInputStream dataInputStream=null; DataOutputStream dataOutputStream = null; String receiveFromClient=""; try { dataInputStream = new DataInputStream(client.getInputStream()); dataOutputStream = new DataOutputStream(client.getOutputStream()); //只是這個線程中一直while循環,不影響其餘的線程。 while(true) { receiveFromClient = dataInputStream.readUTF(); System.out.println("receive: "+receiveFromClient); if(receiveFromClient.equals("bye")) { dataOutputStream.writeUTF("終於厭倦我了嗎?客戶端都是大豬蹄子!!"); dataOutputStream.flush(); break; } else { dataOutputStream.writeUTF("你TM給我發 "+receiveFromClient+" 幹什麼?"); dataOutputStream.flush(); } } }catch (Exception e) { e.printStackTrace(); }finally { try { dataInputStream.close(); dataOutputStream.close(); client.close(); } catch (IOException e) { e.printStackTrace(); } } } }).start(); } }
客戶端代碼:
import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.InputStreamReader; import java.net.Socket; public class MyClient { public static void main(String[] args) throws Exception{ Socket socket = new Socket("127.0.0.1",8852); DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); DataInputStream dataInputStream = new DataInputStream(socket.getInputStream()); BufferedReader bReader = new BufferedReader(new InputStreamReader(System.in)); String string; while(true) { string=bReader.readLine(); dataOutputStream.writeUTF(string); System.out.println(dataInputStream.readUTF()); dataOutputStream.flush(); if(string.equals("bye")) break; } socket.close(); } }
結果展現:
服務器端:
客戶端: