位置:首頁 > Java技術 > Java基礎教程 > Java網絡(Socket編程)

Java網絡(Socket編程)

術語:網絡編程 指的是在多個設備(計算機)執行,其中的設備使用一個網絡中的所有連接到對方編寫程序。

J2SE的API:java.net包中包含的類和提供底層通信細節接口的集合,允許編寫程序方案,重點解決手頭的問題。

java.net包中提供了兩種常用的網絡協議支持:

  • TCP: TCP表示傳輸控製協議,它允許兩個應用程序之間可靠的通信。 TCP通常用於在因特網協議,它被稱為TCP / IP。

  • UDP: UDP代表用戶數據報協議,無連接的協議,允許數據包進行應用程序之間傳輸。

本基礎教程提供了很好的理解以下兩個主題:

  • Socket 編程: 這是在網絡應用最廣泛的概念,它已經在非常詳細地說明。

  • URL 處理: 這將另文學習。點擊這裡了解Java語言的URL處理

Socket 編程:

套接字提供使用TCP兩台計算機之間的通信機製。客戶端程序的通信,其末端創建一個套接字,並嘗試了套接字連接到服務器。

當建立連接時,服務器上的通信,其末端創建一個socket對象。在客戶端和服務器現在可以通過寫入和從socket讀取通信溝通。

java.net.Socket中的類表示一個套接字,將java.net.ServerSocket類提供了一種機製,服務器程序監聽客戶端建立連接。

建立兩台計算機之間建立TCP連接時使用的套接字將執行下列步驟:

  • 服務器實例化一個ServerSocket對象,表示該端口號的通信是在發生。

  • 服務器調用ServerSocket類的accept()方法。這個方法會等到一個客戶端連接到服務器的指定端口上。

  • 服務器正在等待後,一個客戶端實例化一個Socket對象,指定服務器名稱和端口號來連接。

  • Socket類的構造函數會嘗試將客戶端連接到指定的服務器和端口號。如果建立通信,客戶端現在已經能夠與服務器通信的Socket對象。

  • 在服務器端,accept()方法返回一個引用到連接到客戶機的套接字服務器上的一個新的套接字。

在連接建立後,通信可能使用I/O流。每個套接字有兩個一個OutputStream和InputStream。客戶端的OutputStream被連接到服務器的輸入流,並在客戶端的輸入流被連接到服務器的OutputStream中。

TCP是一種雙向通信協議,所以數據可以通過這兩個數據流在同一時間被發送。有下列有用的類提供了一整套實現套接字的方法。

ServerSocket類方法:

java.net.ServerSocket 類用於服務器應用程序,以獲取一個端口,偵聽客戶端請求

ServerSocket類有四個構造函數:

SN 方法及描述
1 public ServerSocket(int port) throws IOException
Attempts to create a server socket bound to the specified port. An exception occurs if the port is already bound by another application.
2 public ServerSocket(int port, int backlog) throws IOException
Similar to the previous constructor, the backlog parameter specifies how many incoming clients to store in a wait queue.
3 public ServerSocket(int port, int backlog, InetAddress address) throws IOException
Similar to the previous constructor, the InetAddress parameter specifies the local IP address to bind to. The InetAddress is used for servers that may have multiple IP addresses, allowing the server to specify which of its IP addresses to accept client requests on
4 public ServerSocket() throws IOException
Creates an unbound server socket. When using this constructor, use the bind() method when you are ready to bind the server socket

如果ServerSocket構造函數不拋出異常,這意味著申請已成功綁定到指定的端口並準備好客戶端請求。

下麵是一些ServerSocket類的常用方法:

SN 方法及描述
1 public int getLocalPort()
Returns the port that the server socket is listening on. This method is useful if you passed in 0 as the port number in a constructor and let the server find a port for you.
2 public Socket accept() throws IOException
Waits for an incoming client. This method blocks until either a client connects to the server on the specified port or the socket times out, assuming that the time-out value has been set using the setSoTimeout() method. Otherwise, this method blocks indefinitely
3 public void setSoTimeout(int timeout)
Sets the time-out value for how long the server socket waits for a client during the accept().
4 public void bind(SocketAddress host, int backlog)
Binds the socket to the specified server and port in the SocketAddress object. Use this method if you instantiated the ServerSocket using the no-argument constructor.

當調用ServerSocket 的accept()方法,該方法不返回,直到一個客戶端連接。當客戶端不連接時,ServerSocket將一個未指定的端口上創建一個新的Socket,並返回一個引用到這個新的Socket。 TCP連接現在在客戶端和服務器之間存在,而且在通訊開始。

Socket類方法:

java.net.Socket中的類表示,無論是客戶端和服務器使用相互通信的套接字。從服務器獲得一個Socket對象accept() 方法返回,客戶端獲得一個Socket對象實例化。

Socket類有一個客戶端用來連接到服務器五個構造函數:

SN 方法及描述
1 public Socket(String host, int port) throws UnknownHostException, IOException.
This method attempts to connect to the specified server at the specified port. If this constructor does not throw an exception, the connection is successful and the client is connected to the server.
2 public Socket(InetAddress host, int port) throws IOException
This method is identical to the previous constructor, except that the host is denoted by an InetAddress object.
3 public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.
Connects to the specified host and port, creating a socket on the local host at the specified address and port.
4 public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.
This method is identical to the previous constructor, except that the host is denoted by an InetAddress object instead of a String
5 public Socket()
Creates an unconnected socket. Use the connect() method to connect this socket to a server.

當Socket構造函數返回時,它不是簡單地實例化一個Socket對象,但它實際上會嘗試連接到指定的服務器和端口。

Socket類感興趣的一些方法在這裡列出。請注意,客戶端和服務器有一個Socket對象,所以這些方法可以通過客戶端和服務器的調用。

SN 方法及描述
1 public void connect(SocketAddress host, int timeout) throws IOException
This method connects the socket to the specified host. This method is needed only when you instantiated the Socket using the no-argument constructor.
2 public InetAddress getInetAddress()
This method returns the address of the other computer that this socket is connected to.
3 public int getPort()
Returns the port the socket is bound to on the remote machine.
4 public int getLocalPort()
Returns the port the socket is bound to on the local machine.
5 public SocketAddress getRemoteSocketAddress()
Returns the address of the remote socket.
6 public InputStream getInputStream() throws IOException
Returns the input stream of the socket. The input stream is connected to the output stream of the remote socket.
7 public OutputStream getOutputStream() throws IOException
Returns the output stream of the socket. The output stream is connected to the input stream of the remote socket
8 public void close() throws IOException
Closes the socket, which makes this Socket object no longer capable of connecting again to any server

InetAddress類的方法:

此類表示互聯網協議(IP)地址。這裡有以下有用的方法,需要在做socket編程用到:

SN 方法及描述
1 static InetAddress getByAddress(byte[] addr)
Returns an InetAddress object given the raw IP address .
2 static InetAddress getByAddress(String host, byte[] addr)
Create an InetAddress based on the provided host name and IP address.
3 static InetAddress getByName(String host)
Determines the IP address of a host, given the host's name.
4 String getHostAddress() 
Returns the IP address string in textual presentation.
5 String getHostName() 
Gets the host name for this IP address.
6 static InetAddress InetAddress getLocalHost()
Returns the local host.
7 String toString()
Converts this IP address to a String.

Socket Client 例子:

下麵GreetingClient是連接到服務器通過使用套接字,並發送問候語,然後等待響應的客戶端程序。

// File Name GreetingClient.java

import java.net.*;
import java.io.*;

public class GreetingClient
{
   public static void main(String [] args)
   {
      String serverName = args[0];
      int port = Integer.parseInt(args[1]);
      try
      {
         System.out.println("Connecting to " + serverName
                             + " on port " + port);
         Socket client = new Socket(serverName, port);
         System.out.println("Just connected to "
                      + client.getRemoteSocketAddress());
         OutputStream outToServer = client.getOutputStream();
         DataOutputStream out =
                       new DataOutputStream(outToServer);

         out.writeUTF("Hello from "
                      + client.getLocalSocketAddress());
         InputStream inFromServer = client.getInputStream();
         DataInputStream in =
                        new DataInputStream(inFromServer);
         System.out.println("Server says " + in.readUTF());
         client.close();
      }catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}

Socket Server 例子:

下麵GreetingServer程序是使用Socket類上通過命令行參數指定的端口號監聽客戶端服務器應用程序的一個示例:

// File Name GreetingServer.java

import java.net.*;
import java.io.*;

public class GreetingServer extends Thread
{
   private ServerSocket serverSocket;
   
   public GreetingServer(int port) throws IOException
   {
      serverSocket = new ServerSocket(port);
      serverSocket.setSoTimeout(10000);
   }

   public void run()
   {
      while(true)
      {
         try
         {
            System.out.println("Waiting for client on port " +
            serverSocket.getLocalPort() + "...");
            Socket server = serverSocket.accept();
            System.out.println("Just connected to "
                  + server.getRemoteSocketAddress());
            DataInputStream in =
                  new DataInputStream(server.getInputStream());
            System.out.println(in.readUTF());
            DataOutputStream out =
                 new DataOutputStream(server.getOutputStream());
            out.writeUTF("Thank you for connecting to "
              + server.getLocalSocketAddress() + "
Goodbye!");
            server.close();
         }catch(SocketTimeoutException s)
         {
            System.out.println("Socket timed out!");
            break;
         }catch(IOException e)
         {
            e.printStackTrace();
            break;
         }
      }
   }
   public static void main(String [] args)
   {
      int port = Integer.parseInt(args[0]);
      try
      {
         Thread t = new GreetingServer(port);
         t.start();
      }catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}

編譯客戶端和服務器,然後啟動服務器,如下所示:

$ java GreetingServer 6066
Waiting for client on port 6066...

檢查客戶端程序如下:

$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!