JAVA网络编程
文章目录
1、网络基础
网络相关概念
网络通信
- **概念:**两台设备之间通过网络实现数据传输
- **网络通信:**将数据通过网络从一台设备传输到另一台设备
- Java. net包下提供了一系列的类或接口,供程序员使用,完成网络通信
网络
**概念:**两台或多台设备通过一定物理设备连接起来构成了网络
根据网络的覆盖范围不同,对网络进行分类
- 局域网:覆盖范围最小,仅仅覆盖一个教室或一个机房
- 城城网:覆盖范围较大,可以覆盖一个城市
- 广域网:覆盖范围最大,可以覆盖全国,甚至全球,万维网是广城网
的代表
IP地址
- **概念:**用于唯一标识网络中的每台计算机
- 查看p地址: ipconfig
- **
ip
地址的表示形式:**点分十进制 XXXXXXXX- **每一个十进制数的范围:**0~255
ip
地址的组成=网络地址+主机地址,比如:192.168.16.69- iPv6是互联网工程任务组设计的用于替代Pv4的下一代P协议,其地址数量号称可以为全世界的每—粒沙子编上一个地址[1]。
- 由于Pv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联的障碍
IPV4地址分类
类型 范围 A 0.0.0.0——127.255.255.255 B 128.0.0.0——191.255…255.255 C 192.0.0.0——223.255.255.255 D 224.0.0.0——239.255.255.255 E 240.0.0.0——247.255.255.255
域名和端口
域名
www.baidu.com
**好处:**为了方便记忆,解决记p的困难
**概念:**将ip
地址映射成域名
端口号
- **概念:**用于标识计算机上某个特定的网络程序
- **表示形式:**以整数形式,范围0~65535
- 0~1024已经被占用比如
- ssh22,
- ftp21,
- smtp25
- http80
- 常见的网络程序端口号
tomcat
:8080mysql
:3306oracle
:1521sqlserver
::1433redis
:6379
网络通信协议
协议
(tcp/ip):TCP/IP(Transmission ControlProtocol/ Internet protoco)
的简写
中文译名为传输控制协议/因特网互联协议
,又叫网络通讯协议
,这个协议是Internet最基本的协议、 Internet国际互联网络的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。[示意图]
OSI模型
OSI/RM协议是由ISO(国际标准化组织)制定的,它有三个基本的功能:提供给开发者一个必须的、通用的概念以便开发完善、可以用来解释连接不同系统的框架。
OSI将计算机网络体系结构(architecture)划分为以下七层:
数据链路层: 决定访问网络介质的方式。
在此层将数据分帧,并处理流控制。本层指定拓扑结构并提供硬件寻址,相当于邮局中的装拆箱工人。
网络层: 使用权数据路由经过大型网络 相当于邮局中的排序工人。
传输层: 提供终端到终端的可靠连接 相当于公司中跑邮局的送信职员。
会话层: 允许用户使用简单易记的名称建立连接 相当于公司中收寄信、写信封与拆信封的秘书。
表示层: 协商数据交换格式 相当公司中简报老板、替老板写信的助理。
应用层: 用户的应用程序和网络之间的接口。
物理层 物理层(Physical Layer)在局部局域网上传送数据帧(data frame),它负责管理计算机通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机适配器等。 数据链路层 数据链路层(Data Link Layer)负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成帧。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网(Wi-Fi)和通用分组无线服务(GPRS)等。 分为两个子层:逻辑链路控制(logic link control,LLC)子层和介质访问控制(media access control,MAC)子层。 网络层 网络层(Network Layer)决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络数据。例如:互联网协议(IP)等。 传输层 传输层(Transport Layer)把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议(TCP)等。 会话层 会话层(Session Layer)负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。 表示层 表示层(Presentation Layer)把数据转换为能与接收者的系统格式兼容并适合传输的格式。 应用层 应用层(Application Layer)提供为应用软件而设的接口,以设置与另一应用软件之间的通信。例如: HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3等。
TCP/IP模型
TCP/IP参考模型是计算机网络的祖父ARPANET和其后继的因特网使用的参考模型。ARPANET是由美国国防部DoD
(U.S.Department of Defense)
赞助的研究网络。逐渐地它通过租用的电话线连结了数百所大学和政府部门。当无线网络和卫星出现以后,现有的协议在和它们相连的时候出现了问题,所以需要一种新的参考体系结构。这个体系结构在它的两个主要协议出现以后,被称为TCP/IP参考模型(TCP/IP reference model)。
TCP/IP模型 各层协议 说明 应用层 HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3,DNS,PRC,SNM 应用层对应于OSI参考模型的高层,为用户提供所需要的各种服务 传输层 TCP/UDP 传输层对应于OSI参考模型的传输层,为应用层实体提供端到端的通信功能,保证了数据包的顺序传送及数据的完整性。 网络层 IP, ICMP, RARP, IGMP 对应于OSI参考模型的网络层,主要解决主机到主机的通信问题。它所包含的协议设计数据包在整个网络上的逻辑传输。注重重新赋予主机一个IP地址来完成对主机的寻址,它还负责数据包在多种网络中的路由。 网络接口层 Link 与OSI参考模型中的物理层和数据链路层相对应。它负责监视数据在主机和网络之间的交换。事实上,TCP/IP本身并未定义该层的协议,而由参与互连的各网络使用自己的物理层和数据链路层协议,然后与TCP/IP的网络接入层进行连接。地址解析协议(ARP)工作在此层,即OSI参考模型的数据链路层。
TCP/UDP协议
TCP协议:
TCP协议:
1.使用TCP协议前,须先建立TCP连接,形成传输数据通道
2.传输前,采用"三次握手"方式,是可靠的
3.TCP协议进行通信的两个应用进程:客户端、服务端
4.在连接中可进行大数据量的传输
5.传输完毕,需释放已建立的连接,效率低建立连接
TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK,并最终对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接,TCP使用的流量控制协议是可变大小的滑动窗口协议。
TCP三次握手的过程如下:
- 客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。
- 服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。
- 客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。
三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。
终止连接
建立一个连接需要三次握手,而终止一个连接要经过四次握手,这是由TCP的半关闭(half-close)造成的。具体过程如下图所示。
某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。
接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。
注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接 收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。
一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。
接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。 [3]
既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。
UDP协议:
UDP协议:
1.将数据、源、目的封装成数据包,不需要建立连接
2.每个数据报的大小限制在64K内
3.因无需连接,故是不可靠的
4.发送数据结束时无需释放资源(因为不是面向连接的),速度快
5.举例:厕所通知:发短信
2、InetAddress
获取本机
InetAddress
对象getLocalHost
根据指定主机名/域名获取ip
地址对象getByName
获取InetAddress
对象的主机名getHostName
获取InetAddress
对象的地址getHostAddress
package com.agony.inetAddress; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Arrays; /** * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ Created with IntelliJ IDEA.(使用IntelliJ IDEA创建。) * ♡ To change this template use File | Settings | File Templates. * ♡ (要更改此模板,请使用文件|设置|文件模板。) * ♡ @Entry name(项目名) : * ♡ @author(作者): agony * ♡ @Time(时间): 2022/1/8 7:52 * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ @Description(描述): * ♡ */ public class Intnet { public static void main(String[] args) throws UnknownHostException { //获取本地主机名及环回地址 System.out.println("获取本地主机名及环回地址==>"); InetAddress loopbackAddress = InetAddress.getLoopbackAddress(); System.out.println(loopbackAddress); //获取本地主机名及ip System.out.println("获取本地主机名及ip==>"); InetAddress localHost = InetAddress.getLocalHost(); System.out.println("localHost:"+localHost); //将本地主机名及ip拆放数组 System.out.println("将本地主机名及ip拆放数组==>"); String[] temp = localHost.toString().split("/"); System.out.println(Arrays.toString(temp)); //获取指定主机名的ip地址 System.out.println("获取指定主机名的ip地址==>"); InetAddress address1 = InetAddress.getByName(temp[1]); System.out.println("address:"+address1); //获取指定域名的主机名及ip地址 System.out.println("获取指定域名的ip地址==>"); InetAddress address2 = InetAddress.getByName("www.baidu.com"); System.out.println("address:"+address2); //获取指定域名的ip地址 System.out.println("获取指定域名的ip地址==>"); String hostAddress = address2.getHostAddress(); System.out.println("hostAddress:"+hostAddress); //获取指定域名的主机名 System.out.println("获取指定域名的主机名==>"); String hostName = address2.getHostName(); System.out.println("hostName:"+hostName); } }
"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" "-javaagent:G:\ij\IntelliJ IDEA
获取本地主机名及ip==>
localHost:DESKTOP-RD775JU/192.168.56.1
将本地主机名及ip拆放数组==>
[DESKTOP-RD775JU, 192.168.56.1]
获取指定主机名的ip地址==>
address:/192.168.56.1
获取指定域名的ip地址==>
address:www.baidu.com/183.232.231.174
获取指定域名的ip地址==>
hostAddress:183.232.231.174
获取指定域名的主机名==>
hostName:www.baidu.com
localhost/127.0.0.1
Process finished with exit code 0
3、Socket
套接字是通信的基石,是支持TCP/IP协议的路通信的基本操作单元。可以将套接字看作不同主机间的进程进行双间通信的端点,它构成了单个主机内及整个网络间的编程界面。套接字存在于通信域中,通信域是为了处理一般的线程通过套接字通信而引进的一种抽象概念。套接字通常和同一个域中的套接字交换数据(数据交换也可能穿越域的界限,但这时一定要执行某种解释程序),各种进程使用这个相同的域互相之间用Internet协议簇来进行通信 [3] 。
Socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。它是网络环境中进程间通信的API(应用程序编程接口),也是可以被命名和寻址的通信端点,使用中的每一个套接字都有其类型和一个与之相连进程。通信时其中一个网络应用程序将要传输的一段信息写入它所在主机的 Socket中,该 Socket通过与网络接口卡(NIC)相连的传输介质将这段信息送到另外一台主机的 Socket中,使对方能够接收到这段信息。 Socket是由IP地址和端口结合的,提供向应用层进程传送数据包的机制 [2] 。
套接字Socket=(IP地址:端口号),套接字的表示方法是点分十进制的lP地址后面写上端口号,中间用冒号或逗号隔开。每一个传输层连接唯一地被通信两端的两个端点(即两个套接字)所确定。例如:如果IP地址是210.37.145.1,而端口号是23,那么得到套接字就是(210.37.145.1:23) [4] 。
类型:
流套接字(SOCK_STREAM)
流套接字用于提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复送,并按顺序接收。流套接字之所以能够实现可靠的数据服务,原因在于其使用了传输控制协议,即TCP(The Transmission Control Protocol)协议 [3] 。
数据报套接字(SOCK_DGRAM)
数据报套接字提供一种无连接的服务。该服务并不能保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。数据报套接字使用UDP( User DatagramProtocol)协议进行数据的传输。由于数据报套接字不能保证数据传输的可靠性,对于有可能出现的数据丢失情况,需要在程序中做相应的处理 [3] 。
原始套接字(SOCK_RAW)
原始套接字与标准套接字(标准套接字指的是前面介绍的流套接字和数据报套接字)的区别在于:原始套接字可以读写内核没有处理的IP数据包,而流套接字只能读取TCP协议的数据,数据报套接字只能读取UDP协议的数据。因此,如果要访问其他协议发送的数据必须使用原始套接 [3] 。
基本介绍
套接字( Socket开发网络应用程序被广泛采用,以至于成为事实上的标准。
通信的两端都要有 Socket,是两台机器间通信的端点
网络通信其实就是 Socket间的通信。
Socket允许程序把网络连接当成一个流,数据在两个 Socket间通过IO传输。
一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
4、TCP
TCP网络编程
字节流
ServerTcpSocket
package com.agony.socket; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; /** * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ Created with IntelliJ IDEA.(使用IntelliJ IDEA创建。) * ♡ To change this template use File | Settings | File Templates. * ♡ (要更改此模板,请使用文件|设置|文件模板。) * ♡ @Entry name(项目名) : * ♡ @author(作者): agony * ♡ @Time(时间): 2022/1/8 9:11 * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ @Description(描述): * ♡ */ public class ServerTcpSocket { public static void main(String[] args) throws IOException { //在本机 9999 端口监听,等待连接 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端 在监听 9999 端口 等待连接..."); //当没有客户端连接9999端口时,程序会阻塞,等待连接 //如果有客户端连接,则会返回 Socket对象,程序继续 Socket socket = serverSocket.accept(); System.out.println("Socket:"+socket); System.out.println(socket.getClass()); //通过socket.getInputStream();拿到输入流 InputStream inputStream = socket.getInputStream(); //I/O流读取 byte[] bytes = new byte[1024]; int readLine = 0; while ((readLine = inputStream.read(bytes)) != -1){ System.out.println(new String(bytes,0,readLine)); } //结束标记 否则会相互阻塞 socket.getInputStream(); //I/O流返回 OutputStream outputStream = socket.getOutputStream(); outputStream.write("Hello Client".getBytes(StandardCharsets.UTF_8)); //结束标记 否则会相互阻塞 socket.shutdownOutput(); //关闭流和socket inputStream.close(); outputStream.close(); socket.close(); serverSocket.close(); } }
"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" "-javaagent:G:\ij\IntelliJ IDEA 服务端 在监听 9999 端口 等待连接... Socket:Socket[addr=/192.168.56.1,port=53916,localport=9999] class java.net.Socket Hello Server Process finished with exit code 0
ClientTcpSocket
package com.agony.socket; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; /** * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ Created with IntelliJ IDEA.(使用IntelliJ IDEA创建。) * ♡ To change this template use File | Settings | File Templates. * ♡ (要更改此模板,请使用文件|设置|文件模板。) * ♡ @Entry name(项目名) : * ♡ @author(作者): agony * ♡ @Time(时间): 2022/1/8 9:08 * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ @Description(描述): * ♡ */ public class ClientTcpSocket { public static void main(String[] args) throws IOException { //连接服务器端(ip,端口) Socket socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端Socket返回:"+socket); System.out.println(socket.getClass()); //通过socket.getOutputStream();拿到输出流 OutputStream outputStream = socket.getOutputStream(); outputStream.write("Hello Server".getBytes(StandardCharsets.UTF_8)); //结束标记 否则会相互阻塞 socket.shutdownOutput(); //I/O流读取 byte[] bytes = new byte[1024]; int readLine = 0; while ((readLine = socket.getInputStream().read(bytes)) != -1){ System.out.println(new String(bytes,0,readLine)); } //结束标记 否则会相互阻塞 socket.getInputStream(); //关闭输出流和socket outputStream.close(); socket.close(); System.out.println("客户端退出"); } }
"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" "-javaagent:G:\ij\IntelliJ IDEA 客户端Socket返回:Socket[addr=DESKTOP-RD775JU/192.168.56.1,port=9999,localport=53916] class java.net.Socket Hello Client 客户端退出 Process finished with exit code 0
字符流
ServerTcpSocket
package com.agony.socket; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; /** * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ Created with IntelliJ IDEA.(使用IntelliJ IDEA创建。) * ♡ To change this template use File | Settings | File Templates. * ♡ (要更改此模板,请使用文件|设置|文件模板。) * ♡ @Entry name(项目名) : * ♡ @author(作者): agony * ♡ @Time(时间): 2022/1/8 9:11 * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ @Description(描述): * ♡ */ public class ServerTcpSocket { public static void main(String[] args) throws IOException { //在本机 9999 端口监听,等待连接 ServerSocket serverSocket = new ServerSocket(9999); System.out.println("服务端 在监听 9999 端口 等待连接..."); //当没有客户端连接9999端口时,程序会阻塞,等待连接 //如果有客户端连接,则会返回 Socket对象,程序继续 Socket socket = serverSocket.accept(); System.out.println("Socket:"+socket); System.out.println(socket.getClass()); //通过socket.getInputStream();拿到输入流 InputStream inputStream = socket.getInputStream(); //I/O流读取 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); System.out.println(reader.readLine()); //I/O流返回 OutputStream outputStream = socket.getOutputStream(); //outputStream.write("Hello Client".getBytes(StandardCharsets.UTF_8)); BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream)); writer.write("字符流,Hello Client"); writer.newLine();//插入一个换行符,表示输入内容结束,注意要求对方使用readLine writer.flush();//刷新后才会写入 //关闭流和socket inputStream.close(); outputStream.close(); reader.close(); writer.close(); socket.close(); serverSocket.close(); } }
"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" "-javaagent:G:\ij\IntelliJ IDEA 服务端 在监听 9999 端口 等待连接... Socket:Socket[addr=/192.168.56.1,port=62831,localport=9999] class java.net.Socket 字符流,Hello Server Process finished with exit code 0
ClientTcpSocket
package com.agony.socket; import java.io.*; import java.net.InetAddress; import java.net.Socket; import java.nio.charset.StandardCharsets; /** * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ Created with IntelliJ IDEA.(使用IntelliJ IDEA创建。) * ♡ To change this template use File | Settings | File Templates. * ♡ (要更改此模板,请使用文件|设置|文件模板。) * ♡ @Entry name(项目名) : * ♡ @author(作者): agony * ♡ @Time(时间): 2022/1/8 9:08 * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ @Description(描述): * ♡ */ public class ClientTcpSocket { public static void main(String[] args) throws IOException { //连接服务器端(ip,端口) Socket socket = new Socket(InetAddress.getLocalHost(),9999); System.out.println("客户端Socket返回:"+socket); System.out.println(socket.getClass()); /*通过socket.getOutputStream();拿到输出流 再通过OutputStreamWriter转换流 进行转化 最后包装流包装BufferedWriter */ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); writer.write("字符流,Hello Server"); writer.newLine();//插入一个换行符,表示输入内容结束,注意要求对方使用readLine writer.flush();//刷新后才会写入 //I/O流读取 /*通过socket.getInputStream();拿到输入流 再通过InputStreamReader转换流 进行转化 最后包装流包装BufferedReader */ BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println(reader.readLine()); //关闭输出流和socket //outputStream.close(); writer.close(); reader.close(); socket.close(); System.out.println("客户端退出"); } }
"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" "-javaagent:G:\ij\IntelliJ IDEA 客户端Socket返回:Socket[addr=DESKTOP-RD775JU/192.168.56.1,port=9999,localport=62831] class java.net.Socket 字符流,Hello Client 客户端退出 Process finished with exit code 0
5、UDP
类
DatagramSocket
和DatagramPacket
实现了基于UDP协议网络程序。UDP数据报通过数据报套接字
DatagramSocket
发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
DatagramPacket
对象封装了UDP数据报,在数据报中包含了发送端的P地址和端口号以及接收端的IP地址和端口号。UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
基本流程:
- 核心的两个类对象
DatagramSocke
与DatagramPacket
- 建立发送端,接收端
- 建立数据包调用
Datagram Socke
的发送、接收方法- 关闭 Datagram Socket
UDP网络编程
UdpA
package com.agony.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.nio.charset.StandardCharsets; /** * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ Created with IntelliJ IDEA.(使用IntelliJ IDEA创建。) * ♡ To change this template use File | Settings | File Templates. * ♡ (要更改此模板,请使用文件|设置|文件模板。) * ♡ @Entry name(项目名) : * ♡ @author(作者): agony * ♡ @Time(时间): 2022/1/9 9:49 * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ @Description(描述): * ♡ */ public class UdpA { public static void main(String[] args) throws IOException { //创建一个 DatagramSocket 对象,监听9999端口 准备接收数据 DatagramSocket socket = new DatagramSocket(9999); System.out.println("A端开始监听9999端口。。。"); //创建一个DatagramPacket对象,接受数据 byte[] buf = new byte[1024]; DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length); //接受数据 socket.receive(datagramPacket); System.out.println("A端:数据已接收"); //拆包 byte[] data = datagramPacket.getData();//接收到的数据 int length = datagramPacket.getLength();//接收到的数据实际长度 System.out.println(new String(data,0,length)); //接收到返回数据 byte[] bytes = "A端已收到数据".getBytes(StandardCharsets.UTF_8); //DatagramPacket(要发送数据,数据长度,主机名,接收端口) DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getLoopbackAddress(), 8888); //发送数据 socket.send(packet); //关闭 socket.close(); System.out.println("A退出。。。"); } }
"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" "-javaagent:G:\ij\IntelliJ IDEA A端开始监听9999端口。。。 A端:数据已接收 n你好啊,。。。。 A退出。。。 Process finished with exit code 0
UdpB
package com.agony.udp; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.nio.charset.StandardCharsets; /** * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ Created with IntelliJ IDEA.(使用IntelliJ IDEA创建。) * ♡ To change this template use File | Settings | File Templates. * ♡ (要更改此模板,请使用文件|设置|文件模板。) * ♡ @Entry name(项目名) : * ♡ @author(作者): agony * ♡ @Time(时间): 2022/1/9 9:49 * ♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡♡ * ♡ @Description(描述): * ♡ */ public class UdpB { public static void main(String[] args) throws IOException { //创建一个 DatagramSocket 对象,8888 准备接收数据 DatagramSocket socket = new DatagramSocket(8888); System.out.println("B端开始监听8888端口。。。"); //创建一个DatagramPacket对象,将要发送数据封装 byte[] bytes = "n你好啊,。。。。".getBytes(StandardCharsets.UTF_8); //DatagramPacket(要发送数据,数据长度,主机名,接收端口) DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, InetAddress.getLoopbackAddress(), 9999); //发送 socket.send(datagramPacket); System.out.println("B端:数据已发送"); //接收回复数据 //创建一个DatagramPacket对象,接受数据 byte[] buf = new byte[1024]; DatagramPacket packet = new DatagramPacket(buf, buf.length); //接受数据 socket.receive(packet); System.out.println("B端:数据已接收"); //拆包 byte[] data = packet.getData();//接收到的数据 int length = packet.getLength();//接收到的数据实际长度 System.out.println(new String(data,0,length)); //关闭 socket.close(); System.out.println("B退出。。。"); } }
"C:\Program Files\Java\jdk1.8.0_311\bin\java.exe" "-javaagent:G:\ij\IntelliJ IDEA B端开始监听8888端口。。。 B端:数据已发送 B端:数据已接收 A端已收到数据 B退出。。。 Process finished with exit code 0