Socket通信模型

socket:兩個Java應用程序可通過一個雙向的網絡通信連接實現數據交互,這個雙向鏈路的一端稱爲一個socket

1.socket通信模型之TCP協議:

java.net包中定義的兩個類Socket和ServerSocket,分別用來是實現雙向鏈接的client端和server端

代碼實現:

客戶端:

public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 6666);//創建socket客戶端,並設置監聽地址及端口
            //向服務端發出消息
            OutputStream outputStream = socket.getOutputStream();//因爲客戶端是要向服務端發出消息,即寫出,因此使用OutputStream()來向socket服務端發送消息
            DataOutputStream dos = new DataOutputStream(outputStream);//爲了方便我們直接寫入字符或數字類型,使用數據流DataOutputStream()對輸出流OutputStream()進行封裝
            dos.writeUTF("Hello Server!");//向輸出流中寫入UTF編碼的字符串
            //接收服務端的消息
            InputStream inputStream = socket.getInputStream();  //接收服務端發出的消息對於客戶端來說爲寫入,因此使用InputStream()來接收socket服務端發送的消息
            InputStreamReader isr = new InputStreamReader(inputStream);//轉換爲字符流
            BufferedReader br = new BufferedReader(isr);//轉換爲緩衝流,從而使用緩衝流的readLine()方法直接讀取一行
            System.out.println(br.readLine());

            dos.flush();//將輸出流管道中的數據做一次推送,保證完全發出去
            dos.close();//關閉輸出流
            isr.close();//關閉輸入流
            socket.close();//關閉socket
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

服務端:

public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(6666);//創建socket服務端,並設置端口號
            Socket socket = serverSocket.accept();//accept()爲接受來自客戶端的請求連接信息,此方法爲阻塞式方法,即沒有客戶端連接的情況下,會一直阻塞在此處,不會往下執行
            System.out.println("連接成功");
            //接收客戶端的消息
            InputStream inputStream = socket.getInputStream();//接收客戶端消息,即爲寫入,因此使用InputStream()來接收Socket客戶端發來的消息
            DataInputStream dis = new DataInputStream(inputStream);//爲了方便我們直接讀取字符或數字類型,使用數據流DataInputStream()對輸入流InputStream()進行封裝
            String result = dis.readUTF();
            System.out.println("收到來自:"+socket.getInetAddress()+":"+socket.getPort()+"的消息:"+result);
            //向客戶端發出消息
            OutputStream outputStream = socket.getOutputStream();//向Socket客戶端發出消息
            OutputStreamWriter osw = new OutputStreamWriter(outputStream);
            osw.write("Hello Client!");

            osw.flush();
            osw.close();
            dis.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

注意:啓動時,需要先啓動服務端,後啓動客戶端

2.Socket通信模型之UDP協議:

UDP協議下來說,是沒有客戶端和服務端之說的,分爲消息的發送方和接收方。

代碼實現:

發送方:

public static void main(String[] args) {
long message = 10000L;    //定義要傳送的“消息”
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();//在內存中創建一塊字節數組區域,用以存放字節數組,並將其轉換爲字節數組,ByteArrayOutputStream()主要作用爲將數據轉爲字節數組
            DataOutputStream dos = new DataOutputStream(baos);//使用數據流DataOutputStream來寫入double/int/float/long等數字類型到字節數組
            dos.writeLong(message);   //將數據寫入到字節數組中,以便於轉換爲字節數組
            dos.flush();
            dos.close();

            byte buf[] = baos.toByteArray();//將剛剛在內存中創建並存放數據的字節數組中的字節數組獲取出來
            DatagramPacket dp = new DatagramPacket(buf,0,buf.length,new InetSocketAddress("127.0.0.1",6789));//UDP協議發出或接收數據需要使用數據包來對數據做一個包裹,因此創建數據包用於包裹字節數組,需註明使用的數組、數組中數據長度
            DatagramSocket ds = new DatagramSocket(9876);//創建UDP協議的Socket對象用以傳輸數據,並設置自己端口號
            ds.send(dp);//send()發送消息
            ds.close();
        }catch (IOException e)
        {
            e.printStackTrace();
        }
}

接收方:

public static void main(String[] args) {
    try {
            byte buf[] = new byte[1024];//定義長度爲1024的字節數組,用於存放字節信息
            DatagramSocket ds = new DatagramSocket(6789);//創建UDP協議的Socket對象用以傳輸數據,並設置自己端口號
            DatagramPacket dp = new DatagramPacket(buf,0,buf.length);//UDP協議發出或接收數據需要使用數據包來對數據做一個包裹,因此創建數據包用於包裹字節數組,需註明使用的數組、數組中數據長度
            ds.receive(dp);//receive()用以接收發送端發出的消息
            //以上操作爲,定義數據載體字節數組以及一個DatagramPacket()來包裹字節數組,DatagramSocket()使用DatagramPacket()來接收數據,最終數據會被存放在buf[]中
            //下邊對buf[]中的數據進行讀取
            ByteArrayInputStream bais = new ByteArrayInputStream(buf);//在內存中創建一塊字節數組區域,用以存放字節數組
            DataInputStream dis = new DataInputStream(bais);//使用數據流DataInputStream來讀取double/int/float/long等數字類型到字節數組
            long message = dis.readLong();  //讀取
            System.out.println("接收到的消息爲:"+message);

            dis.close();
            ds.close();
        }catch (IOException e)
        {
            e.printStackTrace();
        }    
}

注:

1.UDP在傳輸信息時需將消息轉爲字節數組放到數據包DatagramPacket(),上邊使用的ByteArrayInputStream()和ByteArrayOutputStream()是在內存中開闢一塊區域用於存放字節數組,目的是爲了將數字類型的消息轉爲字節數組,使用其提供的toByteArray()即可實現:

2.但是如果我們傳輸的是字符類型的話,可直接使用String提供的getBytes()來得到對應的字節數組:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章