术语:网络编程 指的是在多个设备(计算机)执行,其中的设备使用一个网络中的所有连接到对方编写程序。
J2SE的API:java.net包中包含的类和提供底层通信细节接口的集合,允许编写程序方案,重点解决手头的问题。
java.net包中提供了两种常用的网络协议支持:
TCP: TCP表示传输控制协议,它允许两个应用程序之间可靠的通信。 TCP通常用于在因特网协议,它被称为TCP / IP。
UDP: UDP代表用户数据报协议,无连接的协议,允许数据包进行应用程序之间传输。
本教程提供了很好的理解以下两个主题:
Socket 编程: 这是在网络应用最广泛的概念,它已经在非常详细地说明。
URL 处理: 这将另文学习。点击这里了解Java语言的URL处理。
套接字提供使用TCP两台计算机之间的通信机制。客户端程序的通信,其末端创建一个套接字,并尝试了套接字连接到服务器。
当建立连接时,服务器上的通信,其末端创建一个socket对象。在客户端和服务器现在可以通过写入和从socket读取通信沟通。
java.net.Socket中的类表示一个套接字,将java.net.ServerSocket类提供了一种机制,服务器程序监听客户端建立连接。
建立两台计算机之间建立TCP连接时使用的套接字将执行下列步骤:
服务器实例化一个ServerSocket对象,表示该端口号的通信是在发生。
服务器调用ServerSocket类的accept()方法。这个方法会等到一个客户端连接到服务器的指定端口上。
服务器正在等待后,一个客户端实例化一个Socket对象,指定服务器名称和端口号来连接。
Socket类的构造函数会尝试将客户端连接到指定的服务器和端口号。如果建立通信,客户端现在已经能够与服务器通信的Socket对象。
在服务器端,accept()方法返回一个引用到连接到客户机的套接字服务器上的一个新的套接字。
在连接建立后,通信可能使用I/O流。每个套接字有两个一个OutputStream和InputStream。客户端的OutputStream被连接到服务器的输入流,并在客户端的输入流被连接到服务器的OutputStream中。
TCP是一种双向通信协议,所以数据可以通过这两个数据流在同一时间被发送。有下列有用的类提供了一整套实现套接字的方法。
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连接现在在客户端和服务器之间存在,而且在通讯开始。
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 |
此类表示互联网协议(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. |
下面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(); } } }
下面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() + "/nGoodbye!"); 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!