网络编程
1.在网络通信协议下,实现网络互连的不同计算机上的运行的程序间可以进行数据交换。
网络变成三要素
1.IP地址:每台计算机必须要有唯一标识号。
2.端口:网络的通信本质上是两个应用程序之间的通信,在网络通信时有很多应用程序,而端口号可以看作是应用程序的唯一标识。
3.协议:位于同一网络中进行通信的计算机之间都必须遵守规则,这种规则就是协议。常见协议有UDP,TCP。
IP地址——InetAddress类
1.表示的是一个ip地址对象。
使用静态方法得到该类的对象:static InetAddress getByName(String host) // 参数为主机名,或 字符串类型的IP地址
常用方法:
- String getHostName() // 获取此IP地址的主机名。
- String getHostAddress() // 返回文本显示中的IP地址字符串。
// 通过InetAddress的静态方法创建对象
InetAddress address = InetAddress.getByName("DESKTOP-U1PG1Q4");
// 获取该对象的主机名
String hostname = address.getHostName();
// 获取该对象的IP地址
String hostAddress = address.getHostAddress();
System.out.println("hostname: " + hostname);
System.out.println("hostAddress: " + hostAddress);
端口
1.用两个字节表示的整数。它的取值范围是0~65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用。普通的应用程序需要使用1024以上的端口号,如果一个端口号被另外一个服务或程序所占用,会导致当前程序启动失败。
协议
1.UDP协议:用户数据报协议。它是无连接通信协议。
- UDP协议是一种不可靠的协议,它在通信两端都建立一个Socker对象,但是这两个Socker只是发送接收数据的对象。
- Java中通过DatagramSocket类来实现UDP的Socket
发送数据的步骤:
1.创建发送端的Socket对象。
2.创建数据并打包。
3.调用DatagramSocket对象的方法发送数据。
4.关闭发送端。
DatagramSocket ds = new DatagramSocket();
// 创建一个数据包对象
/*DatagramPacket(byte[] buf, int length, InetAddress address, int port)
构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。*/
byte[] buf = "你好!我是发送端!".getBytes();
int len = buf.length;
InetAddress address = InetAddress.getByName("192.168.0.101");
int port = 10000;
DatagramPacket dp = new DatagramPacket(buf, len, address, port);
ds.send(dp); // 发送数据包
ds.close(); // 关闭发送端
- 接受数据的步骤:
1.创建接收端Sorcket对象(DatagramSorckt)。
2.创建数据包用于接收数据。
3.调用DatagramSorckt方法接受数据。
4.解析数据包并在控制台显示。
5.关闭接收端。
/*DatagramSocket(int port)
构造数据报套接字并将其绑定到本地主机上的指定端口。*/
DatagramSocket ds = new DatagramSocket(10000);
// 创建数据包用于接收数据。
/*DatagramPacket(byte[] buf, int length)
构造一个 DatagramPacket用于接收长度的数据包 length 。 */
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, bys.length);
ds.receive(dp); // 接受数据
// 解析数据包并在控制台显示。
/*byte[] getData() 返回数据缓冲区。 */
// 获取数据包bys中的所有内容,即使内容并没有把bys填满,该方法也会获取到bys后的空数据
byte[] buf = dp.getData();
int length = dp.getLength(); // 获取数据包中的实际长度,去除后面的空数据
System.out.println(new String(buf, 0, length));
ds.close();
2.TCP协议:传输控制协议。他是面向连接的通信协议。必须明确发送端和接收端。每次连接都需要三次握手。常用与文件的上传下载等。
三次握手发生在发送数据的准备阶段,保证了连接的可靠性:
- 第一次握手:客户端向服务端发出连接请求,等待服务端回应。
- 第二次握手:服务端向客户端回送一个响应,通知客户端收到了连接请求。
- 第三次握手:客户端再向服务端发送确认信息,确认连接。
原理:TCP协议是一种可靠的协议。它在两端各建立一个Socket对象,从而在通信的两端实现虚拟链路。一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信。
1.Java对TCP协议做了封装,使用Socket对象表示两端的通信端口,并通过Socket产生IO流来进行网络通信。
2.Java为客户端提供了Socket类,为服务端提供了ServerSocket类
TCP发送步骤:
- 创建客户端Socket对象。
- 创建输出流,写数据。
- 释放流资源。
- 发送。
// 创建客户端Socket对象
// Socket(InetAddress address, int port)创建流套接字并将其连接到指定IP地址的指定端口号。
// Socket s = new Socket(InetAddress.getByName("172.19.172.207"), 12345);
// Socket(host address, int port)创建流套接字并将其连接到指定IP地址的指定端口号。
Socket s = new Socket("172.19.172.207", 12345);
// OutputStream getOutputStream()返回此套接字的输出流。
OutputStream os = s.getOutputStream();
os.write("hello...".getBytes());
s.close();
TCP接收步骤:
- 创建服务器端Socket对象(ServerSocket)。
- 侦听客户端对象返回一个Socket对象,通过accept() 方法。
- 创建输入流读数据,将数据打印在控制台。(这里读数据是通过侦听对象的Socket对象调用getInputStream对象得到的)
- 释放流资源。
// ServerSocket(int port)创建绑定到指定端口的服务器套接字。
ServerSocket ss = new ServerSocket(12345);
//Socket accept()侦听要连接到此套接字并接受它。
Socket accept = ss.accept();
InputStream is = accept.getInputStream();
byte[] bys = new byte[1024];
int len = is.read();
String data = new String(bys, 0, len);
System.out.println(data);
ss.close();
TCP四次挥手
原理:在客户端与服务端取消连接时需要四次挥手,这时客户端会发给服务端一个取消连接的请求,服务端收到后回复一个“等一会”的消息,客户端等,服务端发送给客户端可以取消连接的消息,客户端回一个确认取消。(上述“等一会”是指服务端要对即将取消连接的客户端做最后的数据处理)
服务端优化
1.服务器一旦开启不能随意关闭。
2.UUID类,该类回返回一个随机且唯一的名字对象再toString,解决了名字冲突问题。(随机性极大降低重复率,不是绝对的唯一)
// 创建文件名称随机且唯一
UUID uname = UUID.randomUUID();
System.out.println(uname.toString());
3.使用多线程,实现服务器与多个客户端进行通信。(这么做的资源消耗太严重,所以创建线程池解决)