1. 程式人生 > 其它 >The First Daily Scrum Meeting

The First Daily Scrum Meeting

網路程式設計是指編寫執行在多個裝置(計算機)的程式,這些裝置都通過網路連線起來。

java.net 包中提供了低層次的網路通訊細節。你可以直接使用這些類和介面,來專注於解決問題,而不用關注通訊細節。

java.net 包中提供了兩種常見的網路協議的支援:

  • TCP - TCP 是傳輸控制協議的縮寫,它保障了兩個應用程式之間的可靠通訊。通常用於網際網路協議,被稱 TCP/ IP。
  • UDP - UDP 是使用者資料報協議的縮寫,一個無連線的協議。提供了應用程式之間要傳送的資料的資料包。

一、Socket 和 ServerSocket

套接字(Socket)使用 TCP 提供了兩臺計算機之間的通訊機制。 客戶端程式建立一個套接字,並嘗試連線伺服器的套接字。

Java 通過 Socket 和 ServerSocket 實現對 TCP 的支援。Java 中的 Socket 通訊可以簡單理解為:java.net.Socket 代表客戶端,java.net.ServerSocket 代表服務端,二者可以建立連線,然後通訊。

以下為 Socket 通訊中建立建立的基本流程:

  • 伺服器例項化一個 ServerSocket 物件,表示伺服器繫結一個埠。
  • 伺服器呼叫 ServerSocketaccept() 方法,該方法將一直等待,直到客戶端連線到伺服器的繫結埠(即監聽埠)。
  • 伺服器監聽埠時,客戶端例項化一個 Socket 物件,指定伺服器名稱和埠號來請求連線。
  • Socket 類的建構函式試圖將客戶端連線到指定的伺服器和埠號。如果通訊被建立,則在客戶端建立一個 Socket 物件能夠與伺服器進行通訊。
  • 在伺服器端,accept() 方法返回伺服器上一個新的 Socket 引用,該引用連線到客戶端的 Socket

連線建立後,可以通過使用 IO 流進行通訊。每一個 Socket 都有一個輸出流和一個輸入流。客戶端的輸出流連線到伺服器端的輸入流,而客戶端的輸入流連線到伺服器端的輸出流。

TCP 是一個雙向的通訊協議,因此資料可以通過兩個資料流在同一時間傳送,以下是一些類提供的一套完整的有用的方法來實現 sockets。

ServerSocket

伺服器程式通過使用 java.net.ServerSocket

類以獲取一個埠,並且監聽客戶端請求連線此埠的請求。

ServerSocket 構造方法

ServerSocket 有多個構造方法:

方法 描述
ServerSocket() 建立非繫結伺服器套接字。
ServerSocket(int port) 建立繫結到特定埠的伺服器套接字。
ServerSocket(int port, int backlog) 利用指定的 backlog 建立伺服器套接字並將其繫結到指定的本地埠號。
ServerSocket(int port, int backlog, InetAddress address) 使用指定的埠、監聽 backlog 和要繫結到的本地 IP 地址建立伺服器。

ServerSocket 常用方法

建立非繫結伺服器套接字。 如果 ServerSocket 構造方法沒有丟擲異常,就意味著你的應用程式已經成功繫結到指定的埠,並且偵聽客戶端請求。

這裡有一些 ServerSocket 類的常用方法:

方法 描述
int getLocalPort() 返回此套接字在其上偵聽的埠。
Socket accept() 監聽並接受到此套接字的連線。
void setSoTimeout(int timeout) 通過指定超時值啟用/禁用 SO_TIMEOUT,以毫秒為單位。
void bind(SocketAddress host, int backlog) ServerSocket 繫結到特定地址(IP 地址和埠號)。

Socket

java.net.Socket 類代表客戶端和伺服器都用來互相溝通的套接字。客戶端要獲取一個 Socket 物件通過例項化 ,而 伺服器獲得一個 Socket 物件則通過 accept() 方法 a 的返回值。

Socket 構造方法

Socket 類有 5 個構造方法:

方法 描述
Socket() 通過系統預設型別的 SocketImpl 建立未連線套接字
Socket(String host, int port) 建立一個流套接字並將其連線到指定主機上的指定埠號。
Socket(InetAddress host, int port) 建立一個流套接字並將其連線到指定 IP 地址的指定埠號。
Socket(String host, int port, InetAddress localAddress, int localPort) 建立一個套接字並將其連線到指定遠端主機上的指定遠端埠。
Socket(InetAddress host, int port, InetAddress localAddress, int localPort) 建立一個套接字並將其連線到指定遠端地址上的指定遠端埠。

當 Socket 構造方法返回,並沒有簡單的例項化了一個 Socket 物件,它實際上會嘗試連線到指定的伺服器和埠。

Socket 常用方法

下面列出了一些感興趣的方法,注意客戶端和伺服器端都有一個 Socket 物件,所以無論客戶端還是服務端都能夠呼叫這些方法。

方法 描述
void connect(SocketAddress host, int timeout) 將此套接字連線到伺服器,並指定一個超時值。
InetAddress getInetAddress() 返回套接字連線的地址。
int getPort() 返回此套接字連線到的遠端埠。
int getLocalPort() 返回此套接字繫結到的本地埠。
SocketAddress getRemoteSocketAddress() 返回此套接字連線的端點的地址,如果未連線則返回 null。
InputStream getInputStream() 返回此套接字的輸入流。
OutputStream getOutputStream() 返回此套接字的輸出流。
void close() 關閉此套接字。

Socket 通訊示例

//伺服器端
public class ServiceDemo1 {
    public static void main(String[] args) throws IOException {
        //在伺服器端監聽8888埠
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("伺服器執行中,等待客戶端連線");
        //得到客戶端連線,伺服器會阻塞,直到有一個客戶端連線
        Socket client = serverSocket.accept();
        //獲取客戶端輸出流
        OutputStream outputStream = client.getOutputStream();
        String str = "hello world";
        outputStream.write(str.getBytes());
        outputStream.flush();
        client.close();
        serverSocket.close();
        System.out.println("伺服器訊息傳送完畢,退出");


    }
}
//客戶端
public class ClientDemo1 {
    public static void main(String[] args) throws IOException {
        Socket client = new Socket("localhost",8888);
        InputStream inputStream = client.getInputStream();
        InputStreamReader reader = new InputStreamReader(inputStream);
        BufferedReader bufferedReader = new BufferedReader(reader);
        String str = bufferedReader.readLine();
        System.out.println(str);
        bufferedReader.close();
        reader.close();
        inputStream.close();
        System.out.println("客戶端接受完畢");

    }
}
//使用字元流來傳輸資料
public class TCPClient1 {
    public static void main(String[] args) throws IOException {
        Socket client = new Socket(InetAddress.getLocalHost(),8888);
        OutputStream outputStream = client.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
        writer.write("hello server! 無涯子");
        writer.newLine();//結束標識
        writer.flush();

        //得到伺服器端響應
        InputStream inputStream = client.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String s = reader.readLine();
        System.out.println(s);

        //關閉流資源
        reader.close();
        inputStream.close();
        writer.close();
        outputStream.close();
        client.close();
    }
}

public class TCPServer2 {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(8888);
        System.out.println("伺服器已經開啟埠8888等待連線");
        Socket client = server.accept();
        InputStream inputStream = client.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String s = reader.readLine();
        System.out.println(s);

        OutputStream outputStream = client.getOutputStream();
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
        writer.write("hello client! 無涯子");
        writer.newLine();
        writer.flush();

        //關閉流資源
        writer.close();
        outputStream.close();
        reader.close();
        inputStream.close();
        client.close();
        server.close();
    }
}

二、DatagramSocket 和 DatagramPacket

Java 通過 DatagramSocketDatagramPacket 實現對 UDP 協議的支援。

  • DatagramPacket:資料包類
  • DatagramSocket:通訊類
//UPD通訊伺服器
public class UDPServer {
    public static void main(String[] args) throws Exception {
        String str = "hello world";
        //伺服器在埠3000等待發送到伺服器的訊息
        DatagramSocket datagramSocket = new DatagramSocket(3000);
        DatagramPacket datagramPacket = new DatagramPacket(str.getBytes(),str.length(),
                InetAddress.getByName("localhost"),9000);
        System.out.println("傳送訊息");
        datagramSocket.send(datagramPacket);
        datagramSocket.close();
    }
}
public class UDPClient {
    public static void main(String[] args) throws Exception{
        byte[] buf = new byte[1024];//開闢空間,接受資料
        DatagramSocket ds = new DatagramSocket(9000);
        DatagramPacket dp = new DatagramPacket(buf,1024);//所有資訊使用buf儲存
        ds.receive(dp);
        String str = new String(dp.getData(),0,dp.getLength()) + "from " +
                dp.getAddress().getHostAddress() + ":" + dp.getPort();
        System.out.println(str);
        ds.close();
    }
}
public class UDPClient1 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(3000);
        System.out.println("傳送端開啟UDP3000埠");
        byte[] data = "hello,明天去吃火鍋".getBytes();
        //第三個引數也可以是ip地址,因為這裡是進行本地測試所以是localhost
        DatagramPacket dp = new DatagramPacket(data,data.length, InetAddress.getByName("localhost"),9999);
        ds.send(dp);

        //接受資料
        ds.receive(dp);
        int len = dp.getLength();
        System.out.println(new String(dp.getData(),0,len));
        ds.close();

    }
}
public class UDPServer1 {
    public static void main(String[] args) throws IOException {
        DatagramSocket ds = new DatagramSocket(9999);
        System.out.println("接受端開啟UDP9999埠");
        byte[] data = new byte[1024];
        DatagramPacket dp = new DatagramPacket(data,data.length);
        ds.receive(dp);
        System.out.println(new String(dp.getData(),0,dp.getLength()));
        //響應資料
        data = "ok,沒問題".getBytes();
        dp = new DatagramPacket(data,data.length, InetAddress.getByName("localhost"),3000);
        ds.send(dp);

        ds.close();

    }
}

三、InetAddress

InetAddress 類表示網際網路協議(IP)地址。

沒有公有的建構函式,只能通過靜態方法來建立例項。

四、URL

public class URLDemo1 {
    public static void main(String[] args) throws Exception {
        URL url = new URL("http://www.baidu.com");
        InputStream inputStream = url.openStream();
        InputStreamReader is = new InputStreamReader(inputStream,"utf-8");
        BufferedReader reader = new BufferedReader(is);
        String line;
        while((line = reader.readLine()) != null){
            System.out.println(line);
        }
        reader.close();
        is.close();
        inputStream.close();

    }
}

參考資料

Java 網路程式設計