Java网络编程-学习笔记

152 阅读8分钟

Java 网络编程1. 网络编程三要素2. IP3. IPv4的小细节4. InetAddress类的使用5. 端口号6. 协议7. UDP协议-发送数据8. UDP协议-接受数据9. 单播,组播,广博10. TCP协议(发送和接收)11. http协议12. WebSocket

【黑马Java进阶教程,最详细最全面的Java网络编程教程,含聊天室案例实战】 www.bilibili.com/video/BV1QR…

1. 网络编程三要素

2台电脑要通过网络沟通需要知道:

  1. 对方电脑在互联网中的地址——IP
  2. 我发送消息,对方用什么软件(微信,QQ)去接受消息——端口号 一个端口号只能与一个软件绑定
  3. 网络传输规则——协议

2. IP

分为IPv4,IPv6

bfdc7245adbd9b16eddb7119824cca1

12cc9e2d4912f1ea3fea0044ddb064d

3. IPv4的小细节

1f312cfa0da02eda4d9af07a0fbfe4d

特殊IP地址:

127.0.0.1 也可以是localhost:称为回送地址或回环地址,永远指向本机

常用CMD命令:

ipconfig 查看本机IP

ping 网址 检查与该网址是否连通

4. InetAddress类的使用

InetAddress类的对象,表示的是IP的对象,也可以视为一台电脑的对象

 import java.net.InetAddress;
 ​
 public class test_InetAddress {
     public static void main(String[] args ){
         try{
           // InetAddress类的对象无法显式声明,用getByName
             InetAddress address=InetAddress.getByName("192.168.60.1"); 
             System.out.println(address);
         }catch (Exception e){
             System.out.println(e);
         }
     }
 }

获取到IP的对象(一台电脑的对象)后,调用:

getByName(String host):返回主机的IP地址,host可以为机器名称,也可以是IP地址

getHostName():返回此IP地址的主机名,就是返回这台电脑的名字,我的叫ThinkPad,可自己在windows设置改

getHostAddress():返回文本显示的IP地址字符串

5. 端口号

image-20231017213514692

计算机中每个应用程序与唯一一个端口号进行双向绑定

6. 协议

image-20231017214013284

UDP:面向无连接,就是通信前不管是否建立好连接,直接发,对方能收到就收,不能收到就拉倒

TCP:面向连接,就是通信前先确保连接成功

7. UDP协议-发送数据

image-20231017214449956

 DatagramSocket ds=new DatagramSocket(); // 创建DatagramSocket对象(找快递公司)
 ​
 String msg="First contact!!!"; // 要发送的消息
 byte[] msg_byte = msg.getBytes(); // 转换成byte[]
 ​
 InetAddress address=InetAddress.getByName("127.0.0.1"); // 要发送的目标主机的IP
 int port=10086; // 指定要发到的端口是什么,即目的地是什么
 ​
 DatagramPacket dp=new DatagramPacket(msg_byte, msg_byte.length,address,port); // 创建DatagramPacket对象(打包快递)
 ​
 ds.send(dp); // 发送数据(发送快递)
 ​
 ds.close(); // 释放资源

!!!注意:发送端创建DatagramPacket对象时,需指定InetAddress地址和端口

new DatagramSocket():创建DatagramSocket对象(找快递公司)

底层会有绑定端口的操作,通过这个端口向外发送

空参:从所有可用的端口中随机选择一个来使用

有参:指定端口进行绑定(比如RuoYi-Cloud的9200,9201,9202这些)new DatagramSocket(10086)

new DatagramPacket():创建一个DatagramPacket对象(包裹打包)

参数列表如下:

image-20231018011141432

ds.send(dp):DatagramSocket对象的send方法,传参为DatagramPacket的对象

8. UDP协议-接受数据

image-20231018012320106

先创建一个DatagramSocket的对象,注意接收端的DatagramSocket对象必须绑定端口,这个端口是发送端指定发到的端口

DatagramSocket ds = new DatagramSocket(10086)

再接受打包好的数据之前,我们要先创建一个包裹以接受传来的数据

byte[] bytes = new byte[1024];

DatagramPacket dp = new DatagramPakcet(bytes, bytes.length)

接受包裹:

ds.receive(dp)

 // 创建接收端的DatagramSocket对象。注意接收端的DatagramSocket必须要绑定端口,该端口必须与发送端指定要发到的端口一致
 DatagramSocket ds = new DatagramSocket(10086);
 ​
 // 创建一个包裹,以接受传来的数据
 // 创建接受的byte[]数组
 byte[] bytes = new byte[1024];
 DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
 ​
 // 接受包裹
 System.out.println("开始接受数据...");
 ds.receive(dp); // 接受包裹(阻塞)
 byte[] res = dp.getData(); // dp.getData()接受数据
 int length = dp.getLength(); //dp.getLength()接受的数据长度
 InetAddress address = dp.getAddress(); // dp.getAddress()返回发送端的IP对象(地址)
 int port = dp.getPort(); // dp.getPort()返回交流的端口
 ​
 System.out.println("接受到的数据:");
 System.out.println(new String(res,0,length));
 System.out.println(length);
 System.out.println(address);
 System.out.println(port);
 ​
 // 释放资源
 ds.close();

!!!注意:接收端创建DatagramPacket对象时,可以不指定InetAddress地址和端口

注意这里将byte[]转换为String的方法:new String(res, 0, length)

9. 单播,组播,广博

UDP通信有三种方式:

  1. 单播:这台电脑给对方一台电脑发送消息

  2. 组播:这台电脑给对方一组电脑发送消息

    组播地址:224.0.0.0~224.0.0.255,我给这些地址的任意一个地址发送消息,都代表有一组电脑接受到消息

  3. 广播:这台电脑给对方局域网内所有电脑发送消息

    广播地址:255.255.255.255,给这个地址发送消息,即代表给局域网内所有电脑发送消息

单播:

DatagramSocket

组播:

MuticastSocket

发送端

 // 创建MulticastSocket对象(找组播对应快递公司)
 MulticastSocket ms = new MulticastSocket();
 ​
 // (打包快递)
 String msg = "组播!!!";
 byte[] bytes = msg.getBytes();
 InetAddress address = InetAddress.getByName("224.0.0.1"); // 参数:要发送到的组播地址(目的地)
 int port = 10086;
 DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
 ​
 // (发送包裹)
 ms.send(dp);
 ​
 // 释放资源
 ms.close();

接收端(可以有多个)

 // 创建MulticastSocket对象(找到对应快递公司)
 MulticastSocket multicastSocket = new MulticastSocket(10086);
 ​
 // 创建DatagramPacket对象(创建接收箱子)
 InetAddress address = InetAddress.getByName("224.0.0.1");
 multicastSocket.joinGroup(address); // 将当前本机,加入到224.0.0.1这一组播地址中
 int port = 10086;
 ​
 byte[] bytes = new byte[1024];
 DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length); // 接收端创建DatagramPacket对象时,可以不指定InetAddress地址和端口
 ​
 // 接收包裹
 multicastSocket.receive(datagramPacket);
 byte[] result = datagramPacket.getData();
 int length = datagramPacket.getLength();
 ​
 System.out.println(new String(result, 0, length));

!!!注意,组播的接收端需要将当前本机加入组播地址

广播:

发送端:直接将InetAddress.getByName的参数改为255.255.255.255就行

10. TCP协议(发送和接收)

image-20231018151507474

客户端:发送数据

image-20231018151617458

 // 1.创建发送端Socket对象,需指定要发送给哪台电脑(IP),目标电脑的哪个端口(port)
 Socket socket=new Socket("127.0.0.1",10086);
 ​
 // 2.从Socket对象中获取输出流
 OutputStream outputStream=socket.getOutputStream();
 ​
 // 3.输出信息(注意输出的是字节流byte[])
 outputStream.write("哈喽哈喽,在吗?".getBytes());
 ​
 // 4.释放资源
 outputStream.close();
 socket.close();

服务端:接收数据

image-20231018151726627

 // 1.创建ServerSocket对象,并指定监听的端口
 ServerSocket serverSocket = new ServerSocket(10086);
 ​
 // 2.监听。阻塞式监听。连接成功后会返回一个Socket对象
 Socket socket = serverSocket.accept();
 ​
 // 3.获取输入流。从返回的Socket对象中获取
 InputStream inputStream = socket.getInputStream();
 int b; // 注意!!!InputStream传输的是字节流,可以用int接收
 while ((b = inputStream.read()) != -1) {
     System.out.println((char)b);
 }
 ​
 // 4.释放资源
 socket.close(); // 断开连接
 serverSocket.close(); // 关闭服务器

!!!注意:(char)b会出现传输中文乱码的问题

因为客户端发送数据时使用OutputStream.write(),发送的是字节流。若发送中文,会按照IDEA默认的UTF-8编码表将一个中文转换为3个字节。

服务端用的是InputStream.read(),读的是字节流,每次读一个字节,相当于每次只读1/3个中文,所以乱码。

解决中文乱码问题:用InputStreamReader

 // 原:
 // 3.获取输入流。从返回的Socket对象中获取
 InputStream inputStream = socket.getInputStream();
 int b; // 注意!!!InputStream传输的是字节流,可以用int接收
 while ((b = inputStream.read()) != -1) {
     System.out.println((char)b);
 }
 ​
 ​
 //现:
 // 3.获取输入流。从返回的Socket对象中获取
 InputStream inputStream = socket.getInputStream();
 ​
 InputStreamReader isr = new InputStreamReader(inputStream) // InputStreamReader读的是字符流
 ​
 int b; 
 while ((b = isr.read()) != -1) {
     System.out.println((char)b);
 }

!!!注意:若想要提高读取数据的效率,则可以采用BufferedReader

 InputStream is = new InputStream();
 InputStreamReader isr = new InputStreamReader(is);
 BufferedReader br = new BufferedReader(isr);
 ​
 ​
 // 或者直接嵌套写
 BufferedReader br = new BufferedReader(new InputStreamReader(new InputStream()));

11. http协议

【2小时玩转HTTP协议核心知识 编程 测试开发 网络知识 爬虫】 www.bilibili.com/video/BV1NK…

image-20231022152827352

相关术语

DNS: Domain Name System域名解析服务,提供将域名(如www.baidu.com, www.bing.com)解析为ip地址(百度、必应等的服务器的ip地址)的服务

https: http+SSL,给http协议增添了加密安全传输等的内容

IP: 指IP协议,包括很多内容,IP地址是其包含的概念之一

客户端与服务端的报文格式:

!!!注意:客户端和服务端都是相互的概念。客户端在接收数据的时候也可以叫做“服务端”,服务端发送数据的时候也可以叫做“客户端”。一般发送数据的叫客户端,接收数据的叫服务端。

image-20231022143712769

http协议依赖于TCP、UDP等协议。绝大多数用的是TCP,因为TCP协议采用三次握手机制保证数据能准确无误地传输到服务器

三次握手——使得客户端和服务端知道双方都有发送和接收数据的能力

第一次:客户端将带有SYN标识地数据发送给服务端——证明客户端有发送数据的能力

第二次:服务端将带有SYN/ACK标识的数据发送给客户端——证明服务端有接收客户端数据,并能发送数据给客户端的能力

第三次:客户端再将服务器发来的带有SYN/ACK标识的数据去掉SYN,将ACK标识的数据发给服务器——证明客户端有接收数据的能力

image-20231022151817651

各协议之间的协同完成资源的请求(request)与响应(respose)

image-20231022154846333

一段URL(网址)的解析:

image-20231022161450175

锚点:标记资源的某个位置,比如一段长文本的第一章节,浏览器滚动条直接滚动到第一章节

http报文的组成:

“大头儿子”:请求头很长,内容实体一般很短甚至为空

image-20231022162939288

host:请求的服务器的域名(我要请求这个服务器,这个域名将通过DNS解析成服务器的ip地址)

Connection:连接的模式,keep-alive长连接

Content-Type:内容实体的形式是什么

Content-Length:内容实体的长度

请求方法:

image-20231022163436859

最常用的就是GET(从服务器中获取资源和数据)和POST(向服务器提交资源和数据)

状态码:

image-20231022164233155

12. WebSocket

websocket也是一种传输协议

相比于HTTP需要客户端提出请求,服务端才能发送数据,websocket可以在客户端还没提出请求,就主动给客户端发送数据

websocket客户端(前端)API:

image-20231022204110112

websocke服务端(后端)API:

image-20231022204857649