Java多線程 Socket使用

點我跳過黑哥的卑鄙廣告行爲,進入正文。html

 

Java多線程系列更新中~java

  正式篇:編程

  1. Java多線程(一) 什麼是線程
  2. Java多線程(二)關於多線程的CPU密集型和IO密集型這件事
  3. Java多線程(三)如何建立線程
  4. Java多線程(四)java中的Sleep方法
  5. Java多線程(五)線程的生命週期

  番外篇(神TM番外篇):服務器

  1. Java 過一下基礎
  2. 轉載:java中Thread.sleep()函數使用
  3. Java多線程 Socket使用

 

Socket是客戶端和服務器端交流的端點。經過它能夠實現客戶端和服務器端的通訊。順着這篇文章操做下來,你應該會對Socket編程有比較系統的瞭解。注意,跟着敲代碼,有什麼不懂而我又沒提到的地方,隨時百度,不要積累偏差。網絡

客戶端編程

Socket是有鏈接的,因此雙方創建通訊,須要知道彼此的網絡位置(IP和端口)。多線程

建立Socket對象:socket

Socket socket = new Socket("127.0.0.1",8852);
  • 第一個參數:服務器的IP地址(這裏用的是本機地址)
  • 第二個參數:TCP端口號,其中0~1023是系統保留端口。

爲何須要端口號?例如你想要去找你的暗戀對象告白,你知道她的學校地址(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();
    }
}

結果展現:

服務器端:

客戶端:

相關文章
相關標籤/搜索