# 简介
该部分之所以为 0,是因为在之后 NIO
, AIO
的学习都会大量用到 Socket
的知识,所以为了更好的让读者阅读下去,这里开始对 Socket
做出一点补充。
客户端与服务器连接之后,通过对 Socket
对象的写入和读取进行通信。
连接过程:
- 服务器实例化一个
ServerSocket
对象,表示通过服务器上的端口通信。 - 服务器调用
ServerSocket
类的accept()
方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。 - 服务器正在等待时,一个客户端实例化一个
Socket
对象,指定服务器名称和端口号来请求连接。 Socket
类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个Socket
对象能够与服务器进行通信。- 在服务器端,
accept()
方法返回服务器上一个新的socket
引用,该socket
连接到客户端的socket
。
TCP
是双向通信协议,服务器和客户端可以同时互相发消息。客户端的 Socket 的输出流就是服务端的输入流,客户端的输入流就是服务端的输出流。
# 相关实现类
# ServerSocket 类
服务器应用程序通过该类获取端口(构造函数传入端口),并且监听客户端请求。
构造方法
// 其他三个构造方法,从右至左依次减少一个参数 | |
// 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。 | |
public ServerSocket(int port, int backlog, InetAddress address) throws IOException |
相关方法
// 获取该 Socket 监听的端口 | |
public int getLocalPort() | |
// 侦听并接受到此套接字的连接 | |
public Socket accpet() throws IOException | |
// 将 ServerSocket 绑定到特定地址 (IP 地址和端口号) | |
public void bind(SocketAddress host,int backlog) |
# Socket 类
客户端和服务端通信使用的套接字,客户端要获取一个 Socket
直接实例化,服务端通过 accept
方法返回值。
// 连接到指定主机的指定端口号上 | |
public Socket(String host, int port) | |
// 连接到指定 IP 地址的指定端口号 | |
public Socket(InetAddress host, int port) |
当 Socket
构造方法返回,并没有简单的实例化了一个 Socket
对象,它实际上会尝试连接到指定的服务器和端口。
// 将此套接字连接到服务器,并指定一个超时值。 | |
public void connect(SocketAddress host, int timeout) throws IOException | |
// 返回套接字连接的地址。 | |
public InetAddress getInetAddress() | |
// 返回套接字连接的远程端口,本地端口是 getLocalPort | |
public int getPort() | |
// 获取输入 / 输出流 | |
public OutputStream getOutpurStream(); |
# InetAddress 类
该类表示互联网协议(IP),该类的核心方法,直接在 IDE 里面打出 get
即可。
# 示例
客户端代码
public class Client { | |
public static void main(String[] args) throws IOException { | |
Socket socket = new Socket("127.0.0.1",8888); | |
// 输出流,发送数据给服务端 | |
OutputStream out = socket.getOutputStream(); | |
String s = "hello world"; | |
out.write(s.getBytes()); | |
// 其实也可以是输入流,无非就是接收来自服务器的数据 | |
out.close(); | |
} | |
} |
服务端代码
public class Server { | |
public static void main(String[] args) throws IOException { | |
ServerSocket serverSocket = new ServerSocket(8888); | |
Socket socket = serverSocket.accept(); | |
InputStream in = socket.getInputStream(); | |
byte[] arr = new byte[20]; | |
// 也可以用其他借助装饰者类实现更多功能的类 | |
in.read(arr); | |
server.close(); | |
} | |
} |
其实服务端应该是 while
循环不断获取客户端传过来的连接。我们看到客户端和服务端可以传输数据,这也是 IO 流,比如服务端要获取客户端传过来的数据,就需要调用 read
方法,如果客户端那边数据没准备好,就会一直阻塞在这里。
客户端是一样的道理。既然存在阻塞,那么在设计的时候就存在同步异步问题,也就是之后涉及的 NIO,AIO 等知识。
# 参考
菜鸟教程:https://www.runoob.com/java/java-networking.html