Java 简明教程

Java - Socket Class with Examples

套接字使用 TCP 在两台计算机之间提供通信机制。客户端程序在其通信端创建套接字,并尝试将该套接字连接到服务器。

建立连接时,服务器在其通信端创建一个套接字对象。现在,客户端和服务器可以通过向套接字写入和从套接字读取来进行通信。

java.net.Socket 类表示一个套接字,而 java.net.ServerSocket 类为服务器程序提供了一种机制,用于侦听客户端并与它们建立连接。

建立连接后,可以使用 I/O 流进行通信。每个套接字都有一个 OutputStream 和一个 InputStream。客户端的 OutputStream 连接到服务器的 InputStream,客户端的 InputStream 连接到服务器的 OutputStream。

Java Socket 类表示客户端和服务器都用来相互通信的套接字。客户端通过实例化一个套接字对象来获取一个 Socket 对象,而服务器从 accept() 方法的返回值获取一个 Socket 对象。

Declaration

public class Socket
   extends Object
      implements Closeable

Constructors

Sr.No.

Method & Description

1

public Socket() 此方法创建一个不连接到的套接字,其中包括 SocketImpl 系统默认类型。

2

public Socket(String host, int port) throws UnknownHostException, IOException 此方法尝试连接到指定端口上的指定服务器。如果此构造函数未引发异常,则连接成功,并且客户端连接到服务器。

3

public Socket(String host,int port,InetAddress localAddr,int localPort) throws IOException 此方法创建一个套接字并将其连接到指定的指定远程端口上的远程主机。套接字还将 bind() 到提供的本地地址和端口。

4

public Socket(InetAddress host, int port) throws IOException 此方法与前面的构造函数相同,只不过主机由 InetAddress 对象表示。

5

public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. 此方法与前面的构造函数相同,只不过主机由 InetAddress 对象表示,而不是 String。

6

public Socket(Proxy proxy) 此方法创建一个未连接套接字,指定代理类型(如果有),无论其他设置如何都应使用它。

当 Socket 构造器返回时,它不仅仅实例化一个 Socket 对象,而且实际上尝试连接到指定的服务器和端口。

Methods

此处列出 Socket 类中的一些感兴趣的方法。请注意,客户端和服务器都有一个 Socket 对象,因此客户端和服务器都可以调用这些方法。

Sr.No.

Method & Description

1

void bind(SocketAddress bindpoint) 将套接字绑定到本地地址。

2

void close() Closes this socket.

3

void connect(SocketAddress endpoint) 将此套接字连接到服务器。

4

void connect(SocketAddress endpoint, int timeout) 将此套接字连接到具有指定超时值的服务器。

5

SocketChannel getChannel() 返回与此套接字关联的唯一 SocketChannel 对象(如果有)。

6

InetAddress getInetAddress() 返回套接字连接到的地址。

7

InputStream getInputStream() 返回此套接字的输入流。

8

boolean getKeepAlive() 测试是否启用了 SO_KEEPALIVE。

9

InetAddress getLocalAddress() 获取套接字绑定的本地地址。

10

int getLocalPort() 返回此套接字绑定的本地端口号。

11

SocketAddress getLocalSocketAddress() 返回此套接字绑定的端点的地址。

12

boolean getOOBInline() 测试是否启用了 SO_OOBINLINE。

13

<T> T getOption(SocketOption<T> name) 返回套接字选项的值。

14

OutputStream getOutputStream() 返回此套接字的输出流。

15

int getPort() 返回此套接字连接到的远程端口号。

16

int getReceiveBufferSize() 获取此 Socket 的 SO_RCVBUF 选项的值,即平台用于此 Socket 上的输入的缓冲区大小。

17

SocketAddress getRemoteSocketAddress() 返回此套接字连接到的端点的地址,或在未连接的情况下返回 null。

18

boolean getReuseAddress() 测试是否启用了 SO_REUSEADDR。

19

int getSendBufferSize() 获取 Socket SO_SNDBUF 选项的值,即平台用于对此 Socket 的输出的缓冲区大小。

20

int getSoLinger() 返回 SO_LINGER 的设置。

21

int getSoTimeout() 返回 SO_TIMEOUT 的设置。返回 0 表示禁用此选项(即无穷大超时)。

22

boolean getTcpNoDelay() 测试是否启用了 TCP_NODELAY。

23

int getTrafficClass() 获取从该 Socket 发送的数据包的 IP 标头中的流量等级或服务类型

24

boolean isBound() 返回 Socket 的绑定状态。

25

boolean isClosed() 返回 Socket 的关闭状态。

26

boolean isConnected() 返回 Socket 的连接状态。

27

boolean isInputShutdown() 返回 Socket 连接的读一半是否已关闭。

28

boolean isOutputShutdown() 返回 Socket 连接的写一半是否已关闭。

29

void sendUrgentData(int data) 在 Socket 上发送一个字节的紧急数据。

30

void setKeepAlive(boolean on) Enable/disable SO_KEEPALIVE.

31

void setOOBInline(boolean on) 启用/禁用 SO_OOBINLINE(接收 TCP 紧急数据)默认情况下,禁用此选项,并且在 Socket 上接收到的 TCP 紧急数据将被自动丢弃。

32

<T> Socket setOption(SocketOption<T> name, T value) 设置 Socket 选项的值。

33

void setPerformancePreferences(int connectionTime, int latency, int bandwidth) 为该 Socket 设置性能首选项。

34

void setReceiveBufferSize(int size) 为该 Socket 将 SO_RCVBUF 选项设置为指定值。

35

void setReuseAddress(boolean on) 启用/禁用 SO_REUSEADDR Socket 选项。

36

void setSendBufferSize(int size) 为该 Socket 将 SO_SNDBUF 选项设置为指定值。

37

static void setSocketImplFactory(SocketImplFactory fac) 为应用程序设置客户端 Socket 实施工厂。

38

void setSoLinger(boolean on, int linger) 启用/禁用 SO_LINGER,并设置指定的徘徊时间(秒)。

39

void setSoTimeout(int timeout) 使用指定的超时(以毫秒为单位)启用/禁用 SO_TIMEOUT。

40

void setTcpNoDelay(boolean on) 启用/禁用 TCP_NODELAY(禁用/启用 Nagle 算法)。

41

void setTrafficClass(int tc) 为此套接字设置从该套接字发送的数据包的 IP 头中的流量类型或服务类型八位字节。

42

void shutdownInput() 将该套接字的输入流置于“流的结尾”。

43

void shutdownOutput() 禁用该套接字的输出流。

44

Set<SocketOption<?>> supportedOptions() 返回此套接字支持的套接字选项的集合。

45

String toString() 将此套接字转换为字符串。

Socket Client Example

以下 GreetingClient 是一个客户端程序,它使用套接字连接到服务器并发送问候语,然后等待响应。

Example

package com.tutorialspoint;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

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 类监听命令行参数指定的端口号上的客户端—

package com.tutorialspoint;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

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...
Just connected to /127.0.0.1:49462
Hello from /127.0.0.1:49462
Waiting for client on port 6066...

按照以下步骤检查客户端程序 −

Output

$ 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!