目录
class DatagramSocket (报文套接字) : 用于UDP通信
class DatagramPakcet(报文包):通信过程中的数据抽象
2.订阅(subsrcipt) - 广播(broadcase)模式
传输层的两个重要协议
首先要明确,现在要说的UDP,和马上要说的TCP,都是在传输层工作的协议种类。
UDP:用户报文协议
传输层协议,需要实现进程 to 进程间的通信。
使用UDP协议的两端并未真正连接起来,只是进行数据的传播而已。
UDP没有做过任何处理,就保持网络的原生态状态,没有保护网络的作用,所以不可靠。
TCP:传输控制协议
传输层协议,需要实现进程 to 进程间的通信。
使用TCP协议会将服务器与客户端连接起来。
TCP会做一定的传输控制,让通信变得可靠起来。
UDP与TCP对比
相同点:
都是传输层协议,需要实现进程 to 进程间的通信。
不同点:
UDP:不可靠,无连接,面向数据报文的一种协议。
TCP:可靠,有连接,面向字节流的一种协议。
五元组信息
通信双方IP地址 + 双方port(端口)地址 + 传输层协议 = 五元组信息。
通过五元组信息便可唯一确定网络上的一条通信线路
套接字(Socket)
Socket关键字是站在应用层,做网络编程的一个很重要的概念。
简单来说,在应用层以下,由电脑操作系统硬件来提供通信,
而应用层想要使用网络服务,需要使用OS提供的网络服务窗口 Socket 来享受服务。
Java中使用的UDP协议
class DatagramSocket (报文套接字) : 用于UDP通信
这个类也就是Socket类的一个子类,复制UDP通信,有两种构造方法,
一种带端口参数,用于服务器
一种无参构造,用于客户端
1.UDP服务器
我们使用Socket构造方法创建对象用于服务器端通信
DatagramSocket socket = new DatagramSocket(PORT);
采用一个固定的端口,以方便客户端进行通信,可能会有错误的风险,比如想要通信的时候发现端口被别的进程占用了。
2.UDP客户端
依旧是Socket构造方法,但是不需要传参,我们只作为客户端发送数据给服务器,并且接收服务器回复来的数据即可。
DatagramSocket socket = new DatagramSocket();
3.接收及发送
发送的内容是接下来要讲的报文包类
//接收方法
socket.receive(receivedPacket);
//发送方法
socket.send(sentPacket);
4.关闭
用完之后,记得关闭
socket.close();
class DatagramPakcet(报文包):通信过程中的数据抽象
这个东西相当于就是Socket类要发送的数据包
里面包含了五元组信息 和 数据内容
1.接收方
仅仅是接收一个信件,所以只需要拿一个byte包接收即可。
// 1. 接收请求
byte[] buf = new byte[1024]; // 1024 代表我们最大接收的数据大小(字节)
DatagramPacket receivedPacket = new DatagramPacket(buf, buf.length);
2.发送方
发送方需要提供当前数据内容,已经对方的IP和port
DatagramPacket sentPacket = new DatagramPacket(
bytes, 0, bytes.length, // 要发送的数据
loopbackAddress, TranslateServer.PORT // 对方的 ip + port
);
3.一般用作服务器的方法
InetAddress address = receivedPacket.getAddress();
Log.println("对方的 IP 地址: " + address);
// 拆出对方的端口
int port = receivedPacket.getPort();
Log.println("对方的 port: " + port);
// 拆出对方的 ip 地址 + port
SocketAddress socketAddress = receivedPacket.getSocketAddress();
我们可以得到接收新建的 port , ip 以及数据。
得到port和ip就可以把数据发送回去,所以这是服务器的常用方法。
InetAddress address = receivedPacket.getAddress();
Log.println("对方的 IP 地址: " + address);
// 拆出对方的端口
int port = receivedPacket.getPort();
Log.println("对方的 port: " + port);
有了这些,我们可以把数据再发送回去
首先得到对方的信息
// 拆出对方的 ip 地址 + port
SocketAddress socketAddress = receivedPacket.getSocketAddress();
然后再用Packet打包发送回去
DatagramPacket sentPacket = new DatagramPacket(
sendBuf, 0, sendBuf.length, // 要发送的数据
socketAddress // 从请求信封中拆出来的对象的地址(ip + port)
);
4.一般用作接收者的方法
接收者需要数据,所以getData方法比较常用
byte[] data = receivedPacket.getData();
服务器与客户端
服务器一般是站在应用层角度说的,为目标提供服务
客户端就是享受服务的一端
常见模式
1.请求(Request)-响应(Response)模式
一次请求,一次响应
这个就是说,客户端发送请求,服务器接收并响应,在这个过程中服务器是被动的。
下图是单纯的发送更新情况,没有客户端,服务器之分,由发送端发送数据,接收端接收并更新数据。
下图更符合服务器与客户端之间的交互,客户端先发数据到服务器,经过服务器一系列处理再发回客户端。
通信数据都是采用二进制数据的方式通信,在这里表现为byte[]方式传播。
2.订阅(subsrcipt) - 广播(broadcase)模式
客户端一次订阅,服务器会定期主动推送信息给客户端。
这里的服务器相对来说主动。
UDP总结
1.网络编程的情况
2.如何使用ip + port
3.socket的使用
4.UDP的特点:不可靠,无连接,面向数据报文(数据内容在经过通信时不进行拆封,也就是我不会打开这封信,也就不存在数据改变的问题,对方可以完整接收到数据,当然前提是传出去了)
TCP
TCP是一种可靠,有连接,面向字节流的协议
1.构造方法
作为服务器,我们要创建自己的Socket对象
使用ServerSocket对象
ServerSocket serverSocket = new ServerSocket(PORT);
作为客户端要连接上服务器
使用Socket对象
// 直接创建 Socket,使用服务器 IP + PORT
Log.println("准备创建 socket(TCP 连接)");
Socket socket = new Socket("127.0.0.1", TranslateServerShortConnection.PORT);
2.accept
服务器的Socket对象就是接收客户端得到的,不需要自己创建
监听客户端端口,一旦有客户端连接,返回一个服务器端的Socket对象,并且与此客户端一直相连直到关闭,在此过程其他客户端只能阻塞等待。
Log.println("等待对方来连接");
Socket socket = serverSocket.accept();
Log.println("有客户端连接上来了");
Socket对象就相当于建立起的连接:
3.close
客户端和服务器均可调用此方法来关闭通信
socket.close();
4.Socket获得通信信息
当服务端获取到Socket对象时,便可以调用方法来确定对方的信息。
// 对方信息:
InetAddress inetAddress = socket.getInetAddress(); // ip
Log.println("对方的 ip: " + inetAddress);
int port = socket.getPort(); // port
Log.println("对方的 port: " + port);
SocketAddress remoteSocketAddress = socket.getRemoteSocketAddress(); // ip + port
Log.println("对方的 ip + port: " + remoteSocketAddress);
5.输入流
当接收端接收信息时,就要用输入流接收
InputStream inputStream = socket.getInputStream();
Scanner scanner = new Scanner(inputStream, "UTF-8");
6.输出流
发送数据使用输出流
OutputStream os = socket.getOutputStream();
OutputStreamWriter osWriter = new OutputStreamWriter(os, "UTF-8");
PrintWriter writer = new PrintWriter(osWriter);