目录
- 网络基础
- InetAddress 类
- 成员方法
- UDP 相关 API
- DatagramSocket
- 构造方法
- 成员方法
- DatagramPacket
- 构造方法
- 成员方法
- 发送数据步骤
- 接受数据步骤
- TCP 相关 API
- Client 方 API
- 构造方法
- 成员方法
- TCP 报文接受数据步骤
- Server 方 API
- 构造方法
- 成员方法
- TCP 报文发送流程
网络基础
✨ UDP(用户数据包协议),明显的特点如下:
- 将数据打包(最大不超过 64K)
- 不建立连接
- 速度快
- 不可靠
✨ TCP 协议,具有如下特点:
socket(套接字)是一种抽象层,应用程序通过它来发送和接受数据,就像应用程序打开一个文件句柄,将数据读写到稳定的存储器上一样。使用 socket 可以将应用程序添加到网络中,并与处于同一个网络中的其他应用程序进行通信。一台计算机上的应用程序向 socket 写入的信息能够被另一台计算机上的另一个应用程序读取,反之亦然。
不同类型的 socket 与不同类型的底层协议族以及同一协议族中的不同协议栈相关联,目前 TCP/IP 协议族中的主要 socket 类型为 流套接字(stream socket)和数据包套接字(datagram socket)
- 流套接字将 TCP 作为其端对端协议(底层使用 IP 协议),提供了一个可信赖的字节流服务。一个 TCP/IP 流套接字代表了 TCP 连接的一端
- 数据报套接字使用 UDP 协议(底层同样适用 IP 协议),提供了一个 best-effort 的数据报服务,应用程序可以通过它发送最长 65500 字节的信息。
一个 TCP/IP 套接字由一个互联网地址,一个端对端协议(TCP 协议或 UDP 协议)以及一个端口号唯一确定,下图描述了一个主机中,应用程序、套接字抽象层、协议、端口号之间的逻辑关系。一个套接字抽象层可以被多个应用程序引用。
Socket 具有如下特点:
- 通信的两端都有
socket
- 网络通信其实就是 Socket 间的通信
- 数据在两个 Socket 间通过 IO 流传输数据
Java Socket 常见操作
InetAddress 类
InetAddress 类代表了一个网络目标地址,包括主机名和数字类型的地址信息。该类有两个子类:Inet4Address
和Inet6Address
此类主要进行 IP 地址相关操作,此类没有可以访问的构造方法
一个类没有可以访问的构造方法,可能是如下三种情况:
- 成员全部都是静态的(Math,Arrays,Collections)
- 单例模式(Runtime 类)
- 类中有静态方法返回该类的对象(InetAddress)
成员方法
1 2 3 4 5 6 7 8
| public static InetAddress getByName(String host)throws UnknownHostException;
public static InetAddress getLocalHost()throws UnknownHostException;
public String getHostName();
public String getHostAddress();
|
不知道任何信息时,得到当前主机的主机名以及 IP 地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) { try { InetAddress inetAddress = InetAddress.getLocalHost(); System.out.println(inetAddress); String IP = InetAddress.getLocalHost().getHostAddress(); System.out.println(IP); String name = InetAddress.getLocalHost().getHostName(); System.out.println(name); } catch (UnknownHostException e) { e.printStackTrace(); } }
|
知道主机名或者 IP 地址得到另一个信息
1 2 3 4
| InetAddress address = InetAddress.getByName("Hostname"); System.out.println(address.getHostName()); System.out.println(address.getHostAddress());
|
UDP 相关 API
本小节主要记录与 UDP 相关的 API,不涉及数据质量要求时,UDP 使用的还是非常多的。Java 中与 UDP 相关的主要是如下两个类:DatagramSocket
和DatagramPacket
DatagramSocket
是 UDPSocket 的主要类
构造方法
1 2 3 4
| DatagramSocket(); DatagramSocket(int port); DatagramSocket(int port, InetAddress laddr);
|
成员方法
1 2 3 4 5 6 7 8 9 10
| public void bind(SocketAddress addr)throws SocketException; public void disconnect(); public boolean isBound(); public boolean isConnected(); public boolean isClosed();
public void send(DatagramPacket p)throws IOException;
public void receive(DatagramPacket p)throws IOException;
|
DatagramPacket
UDP 数据包对象,在 UDP 通信时,打包 UDP 发送的数据
构造方法
1 2 3 4
| DatagramPacket(byte[] buf,int length);
DatagramPacket(byte[] buf, int length, InetAddress address, int port);
|
成员方法
1 2 3 4 5 6
| public InetAddress getAddress();
public int getPort();
public int getLength();
|
发送数据步骤
主要步骤如下:
- 创建发送端 Socket 对象
- 创建数据,并把数据打包
- 调用 Socket 对象的发送方法发送数据包
- 释放资源
1 2 3 4 5 6 7 8 9 10 11
| DatagramSocket datagramSocket = new DatagramSocket(); byte[] bytes = "hello,udp,java".getBytes();
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getLocalHost(), 10086);
datagramSocket.send(datagramPacket);
datagramSocket.close();
|
接受数据步骤
UDP 接受数据步骤:
- 创建接收端 Socket 对象
- 创建一个数据包(接受容器)
- 调用 Socket 对象的接收方法接受数据
- 解析数据包,并显示在控制台
- 释放资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) throws IOException { DatagramSocket datagramSocket = new DatagramSocket(10086); byte[] bytes = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length); datagramSocket.receive(datagramPacket); String address = datagramPacket.getAddress().getHostAddress(); String data = new String(datagramPacket.getData(), 0, datagramPacket.getLength()); System.out.println(address + "data is :" + data); datagramSocket.close(); }
|
TCP 相关 API
TCP 协议中的发送数据方称为客户端(Client),接收数据方称为服务端(Server)
Client 方 API
TCP 协议 Client 端的 Socket 对象
构造方法
1 2 3
| Socket(); Socket(InetAddress address, int port); Socket(String host, int port);
|
成员方法
1 2 3 4 5 6
| public OutputStream getOutputStream()throws IOException; public InputStream getInputStream()throws IOException; public InetAddress getInetAddress(); public void shutdownInput()throws IOException; public void shutdownOutput()throws IOException;
|
TCP 报文接受数据步骤
- 创建接受端的 Socket 对象
- 监听客户端,返回一个对应的 Socket 对象
- 获取输入流,读取数据显示在控制台
- 释放资源
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(10086); Socket accept = serverSocket.accept(); InputStream inputStream = accept.getInputStream(); byte[] bytes = new byte[1024]; int len = inputStream.read(bytes); System.out.println( accept.getInetAddress().getHostAddress() + "-----" + new String(bytes, 0, len)); accept.close(); }
|
Server 方 API
TCP 协议 Server 端 Socket 对象
构造方法
1 2 3 4 5
| ServerSocket();
ServerSocket(int port);
|
成员方法
1 2 3 4
| public Socket accept()throws IOException;
public InputStream getInputStream()throws IOException;
|
TCP 报文发送流程
- 创建发送端的 Socket 对象,这一步如果成功,说明连接已经建立成功
- 获取数据流,写数据
- 释放资源
🎶java.net.ConnectException:连接被拒绝
,TCP 协议一定要先打开服务器,而后发送数据,否则连接建立失败
1 2 3 4 5 6 7 8
| public static void main(String[] args) throws IOException { Socket socket = new Socket(InetAddress.getLocalHost(), 10086); OutputStream outputStream = socket.getOutputStream(); outputStream.write("hello tcp !".getBytes()); socket.close(); }
|