声明:以下笔记来源于韩顺平视频https://www.bilibili.com/video/BV1fh411y7R8?p=1,笔记为楼主亲手劳动,劳动不易,转载请标明谢谢。
网络编程
IP 地址
- 概念:用于唯一标识网络中的每台计算机/主机
- 查看ip地址: ipconfig
- ip地址的表示形式:点分十进制xx.xx.xx.xx
- 每一个十进制数的范围: 0~255
- ip地址的组成=网络地址+主机地址,比如: 192.168.16.69
- iPv6是互联网工程任务组设计的用于替代IPv4的下一代IP协议,其地址数量号称可以为全世界的每一 粒沙子编上一 个地址。
- 由于IPv4最大的问题在于网络地址资源有限,严重制约了互联网的应用和发展。IPv6的使用,不仅能解决网络地址资源数量的问题,而且也解决了多种接入设备连入互联网的障碍
域名
- www.baidu.com
- 好处:为了方便记忆,解决记ip的困难
- 概念:将ip地址映射成域名,这里怎么映射上,HTTP协议
端口
概念:用于标识计算机上某个特定的网络程序
表示形式:以整数形式,端口范围O~ 65535 [2个字节表示端口0~2^16-1]
0~1024已经被占用,比如ssh 22, ftp 21, smtp 25 http 80
常见的网络程序端口号:
- tomcat :8080
- mysql:3306
- oracle:1521
- sqlserver:1433
在网络开发中,不要使用0-1024 的端口名花有主。
网络通信协议
TCP/IP (Transmission ControlProtocol/Internet Protocol)的简写,中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议,这个协议是Internet最基本的协议、Internet国际互联网络的基础,简单地说,就是由网络层的IP协议和传输层的TCP协议组成的。
OSI 模型 TCP/IP模型 TCP/IP模型各层对应的协议 应用层 应用层 HTTP//telnet/ftp/DNS 表示层 应用层 HTTP//telnet/ftp/DNS 会话层 应用层 HTTP//telnet/ftp/DNS 传输层 传输层 TCP/UDP/ 网络层 网络层 IP/ICMP/ARP 数据链路层 物理+ 数据链路层 Link 物理层 物理+ 数据链路层 Link
TCP 与 UTP
TCP 协议:
- 使用TCP协议前,须先建立TCP连接,形成传输数据通道
- 传输前,采用"三次握手"方式,是可靠的
- TCP协议进行通信的两个应用进程:客户端、服务端
- 在连接中可进行大数据量的传输
- 传输完毕,需释放已建立的连接,效率低
UTP 协议:
- 将数据、源、目的封装成数据包,不需要建立连接
- 每个数据报的大小限制在64K内,不适合传输大量数据
- 因无需连接,故是不可靠的
- 发送数据结束时无需释放资源(因为不是面向连接的),速度快
InetAddress
获取本机InetAddress对象getLocalHost
根据指定主机名/域名获取ip地址对象getByName
获取InetAddress对象的主机名getHostName
获取InetAddress对象的地址getHostAddress
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DYq1R9Z7-1648481617034)(D:/Typora%20Data/Img/image-20220320155146386.png)]
public class Api_ { public static void main(String[] args) throws UnknownHostException { InetAddress host = InetAddress.getLocalHost(); System.out.println(host);//LAPTOP-OGEO85S7/192.168.179.1 InetAddress host1 = InetAddress.getByName("LAPTOP-OGEO85S7"); System.out.println(host1);//LAPTOP-OGEO85S7/192.168.179.1 InetAddress host1 = InetAddress.getByName("192.168.179.1"); System.out.println(host1);//LAPTOP-OGEO85S7/192.168.179.1 InetAddress host2 = InetAddress.getByName("www.baidu.com"); System.out.println(host2);//www.baidu.com/14.215.177.38 System.out.println(host2.getHostAddress());//14.215.177.38 System.out.println(host2.getHostName());//www.baidu.com } }
Socket
- 套接字(Socket)开发网络应用程序被广泛采用,以至于成为事实上的标准。
- 通信的两端都要有Socket,是两台机器间通信的端点
- 网络通信其实就是Socket间的通信。
- Socket允许程序把网络连接当成一个流, 数据在两个Socket间通过IO传输。
- 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端
TCP 网络通信编程
基于客户端一服务端的网络通信
底层使用的是TCP/IP协议
应用场景举例:客户端发送数据,服务端接受并显示控制台
基于Socket的TCP编程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xl448Evz-1648481617040)(D:/Typora%20Data/Img/image-20220320160241153.png)]
案例1 字节流
- 编写一个服务器端,和一个客户端
- 服务器端在9999端口监听
- 客户端连接到服务器端,发送"hello, server" ,并接收服务器端会送的"hello,client",然后退出
- 服务器端接收到客户端发送的信息,输出,并发送"hello,client",并退出
public class SocketTCP01Client { public static void main(String[] args) throws IOException { Socket socket = new Socket(InetAddress.getLocalHost(), 9999); OutputStream os = socket.getOutputStream(); os.write("hello,world".getBytes()); socket.shutdownOutput();//设置结束标记,尤为重要 byte[] buf = new byte[1024]; int readlen = 0; InputStream is = socket.getInputStream(); while ((readlen = is.read(buf)) != -1) { System.out.println(new String(buf,0,readlen)); } is.close(); os.close(); socket.close(); } }
public class SocketTCP01Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9999); Socket socket = serverSocket.accept(); InputStream is = socket.getInputStream(); byte[] buf = new byte[1024]; int readlen = 0; while ((readlen = is.read(buf)) != -1) { System.out.println(new String(buf,0,readlen)); } OutputStream os = socket.getOutputStream(); os.write("hello,client".getBytes()); socket.shutdownOutput();//设置结束标记,尤为重要 os.close(); is.close(); socket.close(); serverSocket.close(); } }
案例2 字符流
@SuppressWarnings({"all"}) public class SocketTCP02Server { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(9999); Socket socket = serverSocket.accept(); InputStream is = socket.getInputStream(); BufferedReader bufR = new BufferedReader(new InputStreamReader(is)); String readlen = bufR.readLine(); System.out.println(readlen); OutputStream os = socket.getOutputStream(); BufferedWriter bufW = new BufferedWriter(new OutputStreamWriter(os)); bufW.write("hello,client 字符流"); bufW.newLine();//如果用newLine表示结束换行,对方的读入要用readLine才能读到 bufW.flush();//真正写入通道 bufW.close(); bufR.close(); socket.close(); serverSocket.close(); } }
@SuppressWarnings({"all"}) public class SocketTCP02Client { public static void main(String[] args) throws IOException { Socket socket = new Socket(InetAddress.getLocalHost(), 9999); OutputStream os = socket.getOutputStream(); BufferedWriter bufW = new BufferedWriter(new OutputStreamWriter(os)); bufW.write("hello,server 字符流"); bufW.newLine();//表示换行结束十分重要 bufW.flush();//表示真正写入通道,十分重要 InputStream is = socket.getInputStream(); BufferedReader bufR = new BufferedReader(new InputStreamReader(is)); String readLine = bufR.readLine(); System.out.println(readLine); bufR.close(); bufW.close(); socket.close(); } }
网络上传文件案例
要求
- 编写一个服务端,和一个客户端
- 服务器端在8888端口监听
- 客户端连接到服务端,发送一张图片e:\qie.png
- 服务器端接收到客户端发送的图片,保存到src下,发送"收到图片”再退出
- 客户端接收到服务端发送的"收到图片",再退出
- 该程序要求使用StreamUtils.java,我们直接使用
实现
public class TCPFileUploadServer { public static void main(String[] args) throws Exception { ServerSocket serverSocket = new ServerSocket(9999); Socket socket = serverSocket.accept(); BufferedInputStream bis = new BufferedInputStream(socket.getInputStream()); byte[] bytes = StreamUtils.streamToByteArray(bis); String filePath = "d:\\test\\meinv.jpg"; BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath)); bos.write(bytes); BufferedWriter bufW = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); bufW.write("收到图片"); bufW.flush(); socket.shutdownOutput(); bufW.close(); bos.close(); bis.close(); socket.close(); serverSocket.close(); } }
public class TCPFileUploadClient { public static void main(String[] args) throws Exception { Socket socket = new Socket(InetAddress.getLocalHost(), 9999); String filePath = "c:\\test\\meinv.jpg"; BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath)); byte[] bytes = StreamUtils.streamToByteArray(bis); BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream()); bos.write(bytes); socket.shutdownOutput(); InputStream is = socket.getInputStream(); String mes = StreamUtils.streamToString(is); System.out.println(mes); is.close(); bos.close(); bis.close(); socket.close(); } }
netstat 指令
- netstat -an可以查看当前主机网络情况,包括端口监听情况和网络连接情况
- netstat -an | more可以分页显示,空格表示下一页,回车表示下一行
- 要求在dos控制台下执行win+r
- Listening表示某个端口在监听
- 如果有一个外部程序(客户端)连接到该端口,就会显示条连接信息.
- 可以输入ctrI + C退出指令
- netstat -anb 可以查看其占用端口的应用程序
UTP 网络通信编程
类DatagramSocket和DatagramPacket[数据包/数据报]实现了基于UDP协议网络程序。
UDP数据报通过数据报套接字DatagramSocket发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达。
DatagramPacket对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接
基本流程
- 核心的两个类/对象DatagramSocket与DatagramPacket
- 建立发送端,接收端
- 建立数据包
- 调用DatagramSocket的发送、接收方法
- 关闭DatagramSocket
细节说明
- 没有明确的服务端和客户端,演变成数据的发送端和接收端
- 接收数据和发送数据是通过DatagramSocket对象完成
- 将数据封装到DatagramPacket对象/装包
- 当接收到DatagramPacket对象,需要进行拆包,取出数据
- DatagramSocket 可以指定在哪个端口接收数据
练习题
- 编写一个接收端A,和一个发送端B
- 接收端A在9999端口等待接收数据(receive)
- 发送端B向接收端A发送数据"hello ,明天吃火锅~’
- 接收端B接收到发送端A发送的数据,回复 “好的,明天见”,再退出
- 发送端接收回复的数据,再退出
public class UDPReceiverA { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(9999); byte[] buf = new byte[1024];//一般UTP报文最大长度是64k,就是 64 * 1024,这里不需要这么多 DatagramPacket packet = new DatagramPacket(buf, buf.length); socket.receive(packet); int length = packet.getLength(); byte[] data = packet.getData(); System.out.println(new String(data, 0, length)); byte[] bytes = "好的,明天见~".getBytes(); packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("172.20.151.168"), 9998); System.out.println("UDPReceiverA 发送 好的,明天见~ 给 UDPSenderB"); socket.send(packet); socket.close(); } }
public class UDPSenderB { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(9998); byte[] bytes = "hello,明天吃火锅".getBytes(); DatagramPacket packet = new DatagramPacket(bytes, bytes.length, InetAddress.getByName("172.20.151.168"), 9999); System.out.println("UDPSenderB发送hello,明天吃火锅给UDPReceiverA"); socket.send(packet); byte[] buf = new byte[1024];//一般UTP报文最大长度是64k,就是 64 * 1024,这里不需要这么多 packet = new DatagramPacket(buf, buf.length); socket.receive(packet); int length = packet.getLength(); byte[] data = packet.getData(); System.out.println(new String(data, 0, length)); socket.close(); } }
项目开发流程
需求分析
设计阶段
编码实现
测试阶段
实施阶段
维护阶段
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0AEPbysk-1648481617042)(D:/Typora%20Data/Img/image-20220322154231568.png)]