|
套接字编程
Socket 套接字
socket 是操作系统给应用程序提供的 API.
应用程序和 操作系统之间, 相当与应用层和 传输层进行交互. API
其实也就是传输层给应用层提供的.
网络传输层中, 有多种协议, 其中最知名的就是 TCP
和 UDP
. (两个协议的工作特性差别较大, 因此操作系统就提供了两个版本的, 风格迥异的 API).
TCP 与 UDP
TCP | UDP |
---|---|
有连接 | 无连接 |
可靠传输 | 不可靠传输 |
面向字节流 | 面向数据报 |
全双工 | 全双工 |
什么叫做有/ 无连接
比如:
- 打电话是有连接, A 给 B 打电话, B 接了, 才能说话.
- 发短信/ vx 是无连接, 直接发就过去了.
- 有连接, 需要是通信双方建立好连接, 才能通信
- 无连接, 直接发送就可以, 不需要建立连接
什么叫做 (不)可靠传输
- 可靠传输, 不是说 A 给 B 发的数据 ,
100%
能够让 B 收到(网络环境非常复杂, 无法100% 给出承诺). 而是 A 能够知道 B 有没有收到. - 不可靠传输, A 给 B 发的数据, A 并不知道是否发送成功.
面向字节流与数据报
- 面向字节流,
TCP
和文件操作一样, 也是基于 流的. - 面向数据报, 是以 数据报为单位, 不可拆开, 不可一次取半份.
全双工与半双工
- 全双工: 一个通道, 双向通信
- 半双工: 一个通道, 单向通信
一根网线为什么可以双向通信, 还互不干扰 ?
网线里面有 8 根线, 分成两组(其实接 4 根就可以正常使用, 其他备用). 这4 根就相当于 4个车道. 两个进, 两个出.
UDP 的 socket
UDP socket 要掌握的类:
- DatagramSokcet , 用于发送和接收 UDP 数据报
- DatagramPacket, UDP socket 发送和接收的数据报
DatagramSocket API
构造方法:
方法签名 | 方法说明 |
---|---|
DatagramSocket() | 创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端) |
DatagramSocket(int port) | 创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务器) |
方法:
方法签名 | 方法说明 |
---|---|
void receive(DatagramPacket p) | 从此套接字接收数据报 (如果没有接收到数据报,该方法会阻塞等待) |
void send(DatagramPacket p) | 从此套接字发送数据报包 (不会阻塞等待,直接发送) |
void close( ) | 关闭此数据报套接字 |
小知识:
socket
本质上也是文件(广义)socket 对应到 网卡这个硬件设备. 操作系统也是把 网卡当做文件来管理.
- 通过网卡发送数据, 就是 “写文件”
- 通过网卡接收数据, 就是 “读文件”
DatagramPacket API
构造方法:
方法签名 | 方法说明 |
---|---|
DatagramPacket(byte[] buf, int length) | 构造一个 DatagramPackt 以用来接收数据报,接收的数据保存在字节数组 (第一个参数 buf) 中,接收指定长度 (第二个参数 length) |
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address) | 构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组 (第一个参数 buf) 中,从0到指定长度 (第二个参数 length). address 指定目的主机的 IP 和 端口号 |
方法:
方法签名 | 方法说明 |
---|---|
InetAddress getAddress() | 从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址 |
int getPort() | 从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获取接收端主机端口号 |
byte[] getData() | 获取数据报中的数据 |
回显服务器
回显服务器: 客户端发啥, 服务器就返回啥. (回显)
服务器
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket