学习日记(网络编程)

文章目录

  • 学习日记(网络编程)
  • 一、网络通信三要素
    • 1. IP 地址
    • 2. IP 地址操作类:InetAddress
    • 3. 端口号
    • 4. 协议
      • 1. TCP 协议
      • 2. UDP 协议
  • 二、UDP 通信
    • 1. 一发一收
    • 2. 多发一收
    • 3. 一发多收
  • 三、TCP 通信
    • 1. 一发一收
    • 2. 多发一收
    • 3. 使用线程池优化:多发一收
  • 四、即时通信
  • 五、BS 架构模拟
  • 注意:

学习日记(网络编程)

网络编程可以让程序与网络上的其他设备中的程序进行数据交互。

常见的网络通信基本模式有:Client-Server(CS,客户端-服务端)、Browser-Server(BS,浏览器-服务端)。

一、网络通信三要素

  • IP 地址:设备在网络中的地址,是唯一的标识。
  • 端口:应用程序在设备中唯一的标识。
  • 协议:数据在网络中传输的规则,常见的协议有 UDP 协议和 TCP 协议。

1. IP 地址

概述:IP(Internet Protocol):全称是”互联网协议地址“,是分配给上网设备的唯一标志

常见的 IP 分类:IPv4(如点分十进制表示:192.168.1.66)和 IPv6(可以用冒分十六进制表示)。

IP 地址形式:公网地址、私有地址(局域网)。192.168. 开头的就是常见的局域网地址,范围为 192.168.0.0192.168.255.255,专门为组织机构内部使用。

IP 常用命令:ipconfig(查看本机 IP)、ping IP地址或者域名(检查网络是否联通)。

特殊 IP 地址:本机 IP 为:127.0.0.1localhost,这两个称为回送地址本地回环地址,只会寻找当前所在本机。

学习日记(网络编程)_第1张图片

学习日记(网络编程)_第2张图片

2. IP 地址操作类:InetAddress

InetAddress 类表示 Interent 协议(IP)地址。

常用 API 说明
public static InetAddress getLocalHost() 返回本主机的 IP 地址对象,static 方法
public static InetAddress getByName(String host) 得到指定主机的 IP 地址对象,static 方法
public String getHostName() 获取此 IP 对象的主机名
public String getHostAddress() 获取此 IP 对象的地址字符串
public boolean isReachable(int timeout) 在指定毫秒内连通该 IP 地址对应的主机,连通则返回 true,相当于 ping 操作

注意:getByName 方法中参数可以是域名或者是 IP 地址,返回结果为对应的 IP 地址对象。

学习日记(网络编程)_第3张图片

学习日记(网络编程)_第4张图片

3. 端口号

端口号:唯一标识正在计算机设备上运行的进程(程序),被规定为一个 16 位的二进制,范围为 0-65535。

端口类型分为:周知端口、注册端口以及动态端口。

  • 周知端口:0-1023,被预先定义的知名应用占用,如:HTTP 占用 80,FTP 占用 21。
  • 注册端口:1024-49151,分配给用户进程或某些应用程序,如 Tomcat 占用 8080,MySQL 占用 3306。
  • 动态端口:49152-65535,动态端口一般不固定分配某种进程,而是动态分配。

注意:我们自己开发的程序选择注册端口,且一个设备中不能出现两个程序的端口号一样,否则出现端口冲突错误。相反,不同的设备中相同的程序端口号应该相同。

4. 协议

网络通信协议:计算机网络中,连接和通信数据的规则。

网络通信协议有两套参考模型:OSI 参考模型、TCP/IP 参考模型(国际标准)。

TCP/IP 参考模型分为:数据链路层、物理层、网络层、传输层(TCP、UDP 协议)、应用层(程序员一般在这一层开发)。

传输层的两个常见协议:TCP、UDP。

1. TCP 协议

TCP 协议:Transmission Control Protocol,传输控制协议。

协议特点

  • 使用 TCP 协议,必须双方先建立连接,是一种面向连接的可靠通信协议
  • 传输前,采用“三次握手”方式建立连接,点对点的通信,所以是可靠的。
  • 在连接中可以进行大数据量的传输
  • 连接和发送数据都需要确认,且传输完毕后,还需要释放已建立的连接,通信效率较低(相对 UDP 而言)。

通信场景:对信息安全要求较高的场景,例如文件下载、金融等数据通信等。

学习日记(网络编程)_第5张图片

学习日记(网络编程)_第6张图片

2. UDP 协议

UDP 协议:User Datagram Protocol,用户数据报协议。

协议特点

  • UDP 是一种无连接不可靠传输的协议。
  • 将数据源 IP、目的地 IP 以及端口封装成数据包,不需要建立连接
  • 每个数据包的大小限制在 64 KB 内。
  • 发送不管对方是否准备好,接收方收到也不确认,数据不安全,易丢失数据,所以是不可靠的。
  • 可以广播发送,发送数据结束时无需释放资源,开销小,速度快。

通信场景:语音通话、视频会话等。


二、UDP 通信

UDP 有三种通信方式:单播(一发一收、多发一收)、广播(一发多收)、组播(一发多收)。

1. 一发一收

使用 UDP 通信实现一对一客户端发送消息、服务器端接收消息。

总体思路

  • 先创建发送端(接收端)对象;
  • 再创建发送端(接收端)数据包对象;
  • 然后使用发送端(接收端)对象的 send(receive)方法发送(接收)数据到数据包对象中;
  • 最后释放资源。
发送端 or 接收端 构造器 or 方法名 说明
发送端 public DatagramSocket() 创建发送端对象
同上 public DatagramPacket(byte buf[], int length, InetAddress address, int port) 创建发送端数据包对象
同上 public void send(DatagramPacket p) 发送数据包
同上 public void close() 关闭资源
接收端 public DatagramSocket(int port) 创建接收端对象
同上 public DatagramPacket(byte buf[], int length) 创建接收端数据包对象
同上 public void receive(DatagramPacket p) 接收数据包
同上 public int getLength() 得到接收到的实际数据大小
同上 public void close() 关闭资源

注意

  • 创建发送端的 Socket 对象时,系统会随机分配一个端口号,也可以指定端口号。

  • 创建接收端的 Socket 对象时,需要在构造器中指定端口号。

  • 创建发送端数据包对象使用的构造器 DatagramPacket 中参数分别为:要发送内容的字节数组、要发送内容的字节长度、接收端的 IP 地址对象、接收端的端口号。

  • 创建接收端数据包对象使用的构造器 DatagramPacket 中参数分别为:字节数组用来存储接收的内容,能够接收内容的长度。

  • 在接收端如果想知道接收到的实际数据大小,则要调用数据包对象的 getLength 方法。

  • 运行时,应该启动接收端,启动发送端。

学习日记(网络编程)_第7张图片

接收端拓展的 API,都是数据包对象调用

方法名 说明
public SocketAddress getSocketAddress() 获得发送端 IP 地址对象端口号
public InetAddress getAddress() 获得发送端 IP 地址对象
public int getPort() 获得发送端的端口号

学习日记(网络编程)_第8张图片

2. 多发一收

在一发一收的基础上,在发送端和接收端分别加 while 循环,如果输入 exit 则退出。

需求:三个客户端给一个服务器端发消息,实现多发多收。

学习日记(网络编程)_第9张图片

学习日记(网络编程)_第10张图片

运行结果

学习日记(网络编程)_第11张图片

注意:UDP 的接收端可以接收很多发送端的消息,接收端只负责接收数据包,而无所谓是哪个发送端的数据包。

3. 一发多收

一发多收分为广播组播

广播是指当前主机与所在网络中的所有主机通信,步骤

  • 发送端发送的数据包的目的地用广播地址 255.255.255.255,并且指定端口;
  • 本机所在网段的其他主机的程序只要匹配端口成功就可以收到消息了。

注意:广播的数据包不会指定到某个 IP 地址对象,而是用广播地址,这样就发送给了所在网段的其他主机。

学习日记(网络编程)_第12张图片

组播是指当前主机与选定的一组主机的通信,步骤

  • 发送端数据包的目的地是组播 IP,组播地址的范围为:224.0.0.0239.255.255.255
  • 接收端必须绑定(注册)该组播 IP,端口还要对应发送端数据包的目的端口,这样就可以接收该组播消息。

注意:用 DatagramSocket 的子类 MulticastSocket 创建的对象可以在接收端调用 joinGroup 方法绑定组播 IP。

学习日记(网络编程)_第13张图片


三、TCP 通信

在 java 中只要是使用了 java.net.Socket 类实现通信的,底层就是使用了 TCP 协议。

学习日记(网络编程)_第14张图片

1. 一发一收

客户端发送消息步骤

  • 创建客户端的 socket 对象,请求与服务端的连接;
  • 使用 socket 对象调用 getOutputStream 方法得到字节输出流;
  • 将低级管道包装为高级的打印流,并完成数据的发送;

服务端接收消息步骤

  • 创建 ServerSocket 对象,注册服务端端口;
  • 调用 ServerSocket 对象的 accept 方法,等待客户端的连接,并得到 socket 对象;
  • 使用 socket 对象调用 getInputStream 方法得到字节输入流;
  • 将低级管道包装为高级的字符输入流,并完成数据的接收;
客户端 or 服务端 构造器 or 方法名 说明
客户端 public Socket(String host, int port) 创建客户端的 Socket 对象,请求与服务端的连接
同上 public OutputStream getOutputStream() 获得字节输入流对象
服务端 public ServerSocket(int port) 注册服务端端口
同上 public Socket accept() ServerSocket 对象的方法,等待客户端的连接
同上 public InputStream getInputStream() 得到字节输入流对象
同上 public SocketAddress getRemoteSocketAddress() Socket 对象的方法,得到客户端的 socket 地址

注意

  • 创建客户端的 Socket 对象时,参数一为服务端的 IP 地址,参数二为服务端的端口。
  • 客户端怎么发,服务端就应该怎么收,如客户端发一行消息,服务端就应该收一行消息。
  • 客户端如果没有消息,服务端就会进入阻塞等待
  • Socket 一方关闭或者出现异常,对方的 Socket 也会失效或者出错,所以最好不要关闭 Socket 管道。

学习日记(网络编程)_第15张图片

拓展:需要一对一,发送多行消息,接收多行消息。

思路:在客户端加 while 循环,将服务端的 if 改为 while 循环。

学习日记(网络编程)_第16张图片

2. 多发一收

上面的代码不能实现同时接收多个客户端的消息,因为服务端现在是单线程的,每次只能与一个客户端进行通信。而 UDP 的接收端可以接收很多发送端的消息,是因为接收端只负责接收数据包,而无所谓是哪个发送端的数据包,没有建立一对一通信的管道。

实现服务端可以接收多个客户端消息的方法:

  • 主线程定义一个循环负责接收客户端 Socket 管道连接;
  • 每接收到一个 Socket 通信管道后就分配一个独立的线程去负责处理它。

学习日记(网络编程)_第17张图片

代码实现

学习日记(网络编程)_第18张图片

学习日记(网络编程)_第19张图片

运行结果

学习日记(网络编程)_第20张图片

注意:上面代码中提示上下线操作也可以在客户端和服务端实现。

学习日记(网络编程)_第21张图片

学习日记(网络编程)_第22张图片

3. 使用线程池优化:多发一收

使用上面的代码实现多发一收,客户端与服务端是 1:1 的关系,这样客户端并发越多,系统瘫痪就越快。

所以引入线程池来处理多个客户端消息,有以下优点:

  • 服务端可以复用线程处理多个客户端,可以避免系统瘫痪;
  • 适合客户端通信时常较短的场景。

学习日记(网络编程)_第23张图片

代码实现

学习日记(网络编程)_第24张图片

学习日记(网络编程)_第25张图片

学习日记(网络编程)_第26张图片

运行结果

学习日记(网络编程)_第27张图片


四、即时通信

即时通信是指一个客户端的消息发送出去,其他客户端可以接收到,之前 TCP 通信的消息都是发给服务端的,即时通信需要进行端口转发的思想,消息还是要先发给服务端,然后服务端再发给其他客户端。

学习日记(网络编程)_第28张图片

实现思路

  • 三、3 的基础上,在客户端增加收消息的功能。
  • 即时通信需要进行端口转发,所以在服务端,需要把所有在线的 Socket 管道存放在一个 List 集合中,一旦收到一个消息,则把该消息推送给其他管道。
  • 需要在客户端上线或下线时,对 List 集合中的 Socket 管道进行更新。

注意:

  • 因为客户端在发消息的同时,也随时有可能接收消息,所以客户端发送和接收消息应该用两个线程,用线程池来接收消息,用主线程来发送消息。
  • 实际过程中,每个客户端发送消息用到一个线程就可以搞定,所以在客户端发送消息时,用不到线程池;而服务端,需要接收来自许多客户端的消息,所以与每个客户端都需要建立 Socket 管道,所以服务端的接收消息功能,就需要用到线程池。
  • 在服务端端口转发时,不需要知道客户端的 IP 地址和端口号,因为在接收消息时,Socket 管道已经建立,直接传输数据就好。

实现

学习日记(网络编程)_第29张图片

学习日记(网络编程)_第30张图片

学习日记(网络编程)_第31张图片

运行结果

学习日记(网络编程)_第32张图片

学习日记(网络编程)_第33张图片


五、BS 架构模拟

上面的内容都是 CS 架构,客户端需要我们自己开发实现。

BS 架构浏览器访问服务端,不需要开发客户端。

实现 BS 开发,服务器必须给浏览器相应 HTTP 协议格式的数据,否则浏览器不识别。

学习日记(网络编程)_第34张图片

学习日记(网络编程)_第35张图片

代码实现

学习日记(网络编程)_第36张图片

学习日记(网络编程)_第37张图片

在浏览器搜索栏输入服务器地址和端口号127.0.0.1:6666,运行结果

学习日记(网络编程)_第38张图片


注意:

  1. 打开运行快捷键Win + R
  2. 线程池中,临时线程在最大空闲时内,可以继续处理任务。当任务队列中没有任务,且临时线程超过最大空闲时间,临时线程消失。之后,在核心线程正忙,且任务队列中也满时,临时线程仍然可以继续创建。
  3. 设置多例执行

学习日记(网络编程)_第39张图片

  1. 独立功能最好封装为方法。
  2. CS 架构是客户端(需要开发)与服务端建立 Socket 管道进行通信。
  3. BS 架构是浏览器(不需要开发)与服务端建立 Socket 管道进行通信。

你可能感兴趣的:(#,JavaSE,1024程序员节,学习,java,后端)