1.网络通信基本模式
- 常见的通信模式有以下两种:Client-Server(CS)、Browser/Server(BS)
2.网络编程三要素
IP地址: 设备在网络中的地址,是唯一的标识
端口: 应用程序在设备中的唯一标识
协议: 数据在网络中传输的规则,常见的协议有UDP协议和TCP协议
3.IP常用命令
- ipconfig:查看本机IP地址
- ping IP地址:检查网络是否连通
4.特殊IP地址
- 本机IP:127.0.0.1或者localhost:称为回送地址或本地回环地址,只会寻找当前所在本机
5.InetAddress的使用
- 表示Internet协议(IP)地址
名称 | 说明 |
---|---|
public static InetAddress getLocalHost() | 返回本主机的地址对象 |
public static InetAddress getByName(String host) | 得到指定主机的IP地址对象,参数是域名或者IP地址 |
public String getHostName() | 获取此IP地址的主机名 |
public String getHostAddress() | 返回IP地址字符串 |
public boolean isReachable(int timeout) | 在指定毫秒内连通该IP地址对应的主机,连通返回true;相当于ping |
6.端口号
- 标识正在计算机设备上运行的进程(程序),被规定为一个16位的二进制,范围是0~65535
端口类型
- 周知端口:0~1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21)
- 注册端口:1024~49151,分配给用户进程或某些应用程序。(如:Tomcat占用8080,MySQL占用3306)
- 动态端口:49152~65535,一般不固定分配某种进程,而是动态分配
注意:自己开发的程序选择注册端口,且一个设备中不能出现两个程序的端口号一样
7.UDP协议
- 无连接,不可靠;将数据源IP、目的地IP和端口以及数据封装成数据包,大小限制在64KB内,直接发送出去即可
DatagramPacket:数据包对象
构造器 | 说明 |
---|---|
public DatagramPacket(byte[ ] buf, int length, InetAddress address, int port) | 创建发送端数据包对象 buf:要发送的内容,字节数组 length:要发送内容的字节长度 address:接收端的IP地址对象 port:接收端的端口号 |
public DatagramPacket(byte[ ] buf, int length) | 创建接收端的数据包对象 buf:用来存储接收的内容 length:能够接收内容的长度 |
public int getLength() | 获得实际接收到的字节个数 |
DatagramSocket:发送端和接收端对象
方法 | 说明 |
---|---|
public DatagramSocket() | 创建发送端的Socket对象,系统随机分配一个端口号 |
public DatagramSocket(int port) | 创建接收端的Socket对象并指定端口号 |
public void send(DatagramPacket dp) | 发送数据包 |
public void receive(DatagramPacket p) | 接收数据包 |
8.UDP通信-广播、组播
- 单播:单台主机与单台主机之间的通信
- 广播:当前主机与所在网络中的所有主机通信
- 组播:当前主机与选定的一组主机的通信
实现广播:
- 使用广播地址:255.255.255.255
- 发送端发送的数据包的目的地写的是广播地址、且指定端口(255.255.255.255,9999)
- 本机所在网段的其他主机的程序只要匹配端口成功即可接收消息(9999)
实现组播:
- 使用组播地址:224.0.0.0~239.255.255.255
- 发送端的数据包的目的地是组播IP(例如:224.0.1.1,端口:9999)
- 接收端必须绑定该组播IP(224.0.0.1),端口还要对应发送端的目的端口9999,这样既可接收消息
- DatagramSocket的子类MulticastSocket 可以在接收端绑定组播IP,并使用joinGroup()方法绑定组播IP
9.TCP通信
TCP连接使用Socket进行通信,若其中一方的Socket关闭或者异常,另一个也会跟着失效或者出错
客户端Socket:
方法 | 说明 |
---|---|
public Socket(String host, int port) | 创建发送端的Socket对象与服务端连接,参数为服务端程序的ip和端口 |
OutputStream getOutputStream() | 获得字节输出流对象 |
InputStream getInputStream() | 获得字节输入流对象 |
实现步骤:
- 创建客户端的Socket对象,请求与服务端的连接
- 使用Socket对象调用getOutputStream()方法得到字节输出流
- 包装成打印流完成数据的发送 (记得flush)
- 释放资源:关闭socket通道 (一般不关闭,防止数据还没有成功发送过去,或者对方还没接收完,管道断开会导致对方跟着断开)
服务端ServerSocket:
方法 | 说明 |
---|---|
public ServerSocket(int port) | 注册服务端端口 |
public Socket accept() | 等待接收客户端的Socket通信连接,连接成功返回Socket对象与客户端建立端到端通信 |
实现步骤:
- 创建ServerSocket对象,注册服务端端口
- 调用ServerSocket对象的accept()方法,等待客户端的连接,成功连接后得到Socket管道对象
- 通过Socket对象调用getInputStream()方法得到字节输入流,完成数据的接收 (一般使用缓冲字符流接收,注意,如果使用readLine()方法,那么客户端必须发送一行数据,带换行符)
- 释放资源,关闭socket管道
10.TCP同时处理多个客户端的请求
- 使用多线程技术
- 主线程定义了循环负责接收客户端Socket 管道连接
- 每接收到一个Socket通信管道后分配一个独立的线程负责处理它
问题:
- 客户端与服务端的线程模型是:N-N的关系
- 客户端并发越多,系统瘫痪的越快
11.引入线程池处理多个客户端消息
- 服务端可以复用线程处理多个客户端,可以避免系统瘫痪
- 适合客户端通信时长较短的场景
12.TCP即时通信
- 端口转发:先把消息发给服务端,服务端再发给客户端
- 服务端需要把在线的Socket存储起来
13.JUnit单元测试
- 单元测试就是针对最小的功能单元编写测试代码,Java程序最小的功能单元是方法
实现步骤:
- 将JUnit的jar包导入项目(IDEA整合好了),如果没有整合好,手工导入hamcrest-core-1.3.jar和junit-4.12.jar
- 编写测试方法:必须是公共的无参数无返回值的非静态方法
- 在测试方法上使用@Test注解:标注该方法是一个测试方法
- 在测试方法中完成被测试方法的预期正确性测试
断言Assert
JUnit常用注解:
注解 | 说明 |
---|---|
@Test | 测试方法 |
@Before | 用来修饰实例方法,该方法会在每一个测试方法执行之前执行一次 |
@After | 用来修饰实例方法,该方法会在每一个测试方法执行之后执行一次 |
@BeforeClass | 用来修饰静态方法,该方法会在所有测试方法之前只执行一次 |
@AfterClass | 用来修饰静态方法,该方法会在所有测试方法之后只执行一次 |