首頁  >  文章  >  Java  >  深入理解Java Socket通訊的分析

深入理解Java Socket通訊的分析

黄舟
黄舟原創
2017-03-07 10:21:121724瀏覽

本篇文章主要介紹了深入理解Java Socket,Java中的網路通訊是透過Socket實現的,Socket分為ServerSocket和Socket兩大類,有興趣的可以了解一下

#簡述

Java中Socket分為普通Socket和NioSocket兩種,這裡介紹Socket。

我們可以把Socket比喻成兩個城市間的交通工具,有了它可以在兩城之間來回穿梭,交通工具有很多種,每種交通工具也有相應的交通規則。 Socket也是一樣,也有多種。大多情況下使用的是TCP/IP的流套接字,它是一種穩定的通訊協定。 (TCP/IP與UDP的對比)

Java中的網路通訊是透過Socket實現的,Socket分為ServerSocket和Socket兩大類,ServerSocket用於服務端,透過accept方法監聽請求,監聽到請求後返回Socket,Socket用於具體完成資料傳輸,客戶端直接使用Socket發起請求並傳輸資料。

ServerSocket的使用可以分成三個步驟:

1.建立ServerSocket。 ServerSocket的建構方法總共有5個,通常用的是ServerSocket(int port),只需要連接埠號碼(port)即可。

2.呼叫建立出來的ServerSocket的accept方法進行監聽。 accept方法時阻塞方法,也就是說呼叫accept方法後程式會停下來等待連線請求,在接收到請求之前程式將不會往下走。當接收到請求後accept方法會回傳一個Socket。

3.使用accept方法傳回的Socket與客戶端進行通訊。

栗子

Client:

#
package IO;

import java.io.*;
import java.net.Socket;
import java.util.Date;

/**
 * Created by zhengbin06 on 2017/2/2.
 */
public class Client {
  public static void main(String[] args) {
    String msg = "Client Data";
    try {
      Socket socket = new Socket("127.0.0.1", 9090);

      // 先写、再读
      PrintWriter printWriter = new PrintWriter(socket.getOutputStream());
      // 发送数据
      printWriter.println(msg);
      printWriter.flush();
      // 获得服务端返回的数据
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      String line = bufferedReader.readLine();
      System.out.println("received from server: " + line + "\ttime=" + new Date().getTime());
      // 关闭资源
      printWriter.close();
      bufferedReader.close();
      socket.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

##Server:


package IO;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

/**
 * Created by zhengbin06 on 2017/2/2.
 */
public class Server {
  private static Socket socket = null;
  private static ServerSocket serverSocket = null;
  public static void main(String[] args) throws IOException {
    BufferedReader bufferedReader = null;
    PrintWriter printWriter = null;
    try {
      // 创建一个ServerSocket监听9090端口
      serverSocket = new ServerSocket(9090);
      while (true) {
        System.out.println("开始等待请求。。。。");
        // 等待请求
        // 监听并接受到此套接字的连接。此方法在连接传入之前一直阻塞。
        socket = serverSocket.accept();
        System.out.println("接收到请求:" + socket.toString() + "\ttime=" + new Date().getTime());
        // 接收到请求后使用socket进行通信, 创建BufferedReader用于读取数据
        bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String line = bufferedReader.readLine();
        System.out.println("received from client: " + line + "\ttime=" + new Date().getTime());
  
        // 创建PrintWriter, 用于发送数据
        printWriter = new PrintWriter(socket.getOutputStream());
        printWriter.println("received data: " + line + "\ttime=" + new Date().getTime());
        printWriter.flush();
      }
    } finally {
      // 关闭所有资源
      bufferedReader.close();
      printWriter.close();
      socket.close();
      serverSocket.close();
    }
  }
}

細節

#監聽請求:##當一個新的Socket當請求來到時,將為這個連接創建一個新的套接字資料結構,該套接字資料的資訊包含的位址和連接埠正式請求來源位址和連接埠。這個新建立的資料結構將會關聯到ServerSocket實例的一個未完成的連接資料結構清單中。注意,這時服務端的與之對應的Socket實例並沒有完成創建,而要等到與客戶端的3次握手完成後,這個服務端的Socket實例才會返回,並將這個Socket實例對應的資料結構從未完成清單中移動已完成清單中。

資料傳輸:

當連線已經建立成功時,服務端和用戶端都會擁有一個Socket實例,每個Socket實例都有一個InputStream和OutputStream,並透過這兩個物件來交換資料。


要知道網路I/O都是以位元組流傳輸的,當創建Socket物件時,作業系統將會為InputStream和OutputStream分別分配一定大小的快取區,資料的寫入和讀取都是透過這個快取區完成的。


寫入端將資料寫入OutputStream對應的SendQ佇列中,當佇列填滿時,資料將被轉移到另一端InputStream的RecvQ佇列中,如果這時RecvQ已經滿了,那麼OutputStream的write方法將會阻塞,直到RecvQ佇列有足夠的空間容納SendQ所傳送的資料。過程如下圖:


 以上就是深入理解Java Socket通訊的分析的內容,更多相關內容請關注PHP中文網(www.php. cn)!


#

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn