目录
1、UDP(User Datagram Protocol)用户数据报协议
1、TCP(Transmission Control Protocol)传输控制协议
网络通信
1、基本通信架构
CS架构(Client客户端 / Server服务端)、BS架构(Browser浏览器 / Server服务端)
2、网络通信三要素
- ip:设备在网络中的地址
- 端口:应用程序在设备中的唯一标识(周知端口、注册端口、动态端口)
- 协议:链接、数据在网络传输中的规则
其中ip又分为ip4和ip6(感兴趣的可以网上看看相关的资料),通过ipconfig可以查看本机的ip地址。
3、Java中的ip对象InetAddress
Java.net.*包下提供了一些获取ip对象InetAddress的相关方法:
UDP通信
1、UDP(User Datagram Protocol)用户数据报协议
特点:无连接、不可靠通信,通信效率高。
以包为单位,包含自己ip、程序端口、目的ip、目的程序端口、数据(64kb以内)。
不管对方是否接到、数据是否丢失,因而效率高、不可靠。
2、Java中的UDP通信
Java.net.DatagramSocket包可以实现UDP通信
package ahaaaa.cn.net.udp.udp2;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
/**
* Description of the class.
*
* @Author ahaaaa
* @Date 2023-09-03 17:39
* @Description 客户端发送信息
*/
public class UDPCommunicationClient {
public static void main(String[] args) throws Exception {
// 客户端
DatagramSocket datagramSocket = new DatagramSocket(8888);
// 数据(最大不超过64kb)
Scanner scanner = new Scanner(System.in);
while (true){
System.out.println("please:");
String message = scanner.nextLine();
// 断开
if ("exit".equals(message)){
System.out.println("exit success!");
datagramSocket.close();
break;
}
byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
// 封装UDP传输中包所需要的的信息
InetAddress localHost = InetAddress.getLocalHost();
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, localHost, 9999);
// 发送数据
datagramSocket.send(datagramPacket);
}
}
}
package ahaaaa.cn.net.udp.udp2;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
/**
* Description of the class.
*
* @Author ahaaaa
* @Date 2023-09-03 17:40
* @Description 服务端接收信息
*/
public class UDPCommunicationServer {
public static void main(String[] args) throws Exception {
System.out.println("-----UDPCommunicationServer Start-----");
// 服务端
DatagramSocket datagramSocket = new DatagramSocket(9999);
// 数据对象接收数据
byte[] bytes = new byte[64 * 1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
while(true){
datagramSocket.receive(datagramPacket);
// 处理数据
int length = datagramPacket.getLength();
String message = new String(bytes, 0, length);
System.out.println(message);
// 获取对方主机名和地址
System.out.println(datagramPacket.getAddress().getHostName());
System.out.println(datagramPacket.getAddress().getHostAddress()+":"+datagramPacket.getPort());
System.out.println("---------------------------------------------------");
}
}
}
TCP通信
1、TCP(Transmission Control Protocol)传输控制协议
特点:面向链接、可靠通信、效率低
需要三次握手确认连接,四次挥手断开链接。
三次握手:
四次挥手:
注:这里简单的接受一下为啥服务端要两次响应,收到请求后,服务端需要处理完数据才能断开,因此会先响应请求,处理完数据后再发送确认断开连接。而后客户端发送最后一个请求告知服务端自己有接收到正式断开请求并正式断开。
2、Java中的TCP通信
Java.net.DatagramSocket包可以实现UDP通信
package ahaaaa.cn.net.tcp.tcp2;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
/**
* Description of the class.
*
* @Author ahaaaa
* @Date 2023-09-03 18:17
* @Description tcp-多个客户端发送
*/
public class TCPCommunicationClient {
public static void main(String[] args) throws Exception {
// 客户端对象
Socket socket = new Socket("127.0.0.1", 9999);
// 从通信管道获取输出流
OutputStream outputStream = socket.getOutputStream();
DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
Scanner scanner = new Scanner(System.in);
// 处理数据
while (true){
System.out.print("please:");
String message = scanner.nextLine();
if ("exit".equals(message)){
System.out.println("exit success!");
dataOutputStream.close();
socket.close();
break;
}
dataOutputStream.writeUTF(message);
dataOutputStream.flush();
}
}
}
package ahaaaa.cn.net.tcp.tcp2;
import java.net.ServerSocket;
import java.net.Socket;
/**
* Description of the class.
*
* @Author ahaaaa
* @Date 2023-09-03 18:18
* @Description 服务端接收多个客户端
*/
public class TCPCommunicationServer {
public static void main(String[] args) throws Exception {
System.out.println("-----TCPCommunicationServer Start-----");
// 服务端
ServerSocket serverSocket = new ServerSocket(9999);
// 处理
while (true){
// 等待请求
Socket accept = serverSocket.accept();
System.out.println("有人上线了:" + accept.getRemoteSocketAddress());
new ServerReaderThread(accept).start();
}
}
}
package ahaaaa.cn.net.tcp.tcp2;
import java.io.DataInputStream;
import java.io.InputStream;
import java.net.Socket;
/**
* Description of the class.
*
* @Author ahaaaa
* @Date 2023-09-04 11:31
* @Description null
*/
public class ServerReaderThread extends Thread{
private Socket socket;
public ServerReaderThread(Socket socket){
this.socket = socket;
}
@Override
public void run() {
try {
// 从管道中获取输入流
InputStream inputStream = socket.getInputStream();
DataInputStream dataInputStream = new DataInputStream(inputStream);
// 处理
while (true){
try {
String readUTF = dataInputStream.readUTF();
System.out.println(readUTF);
}catch (Exception e){
System.out.println(socket.getRemoteSocketAddress() + "离线了!");
dataInputStream.close();
socket.close();
break;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}
以上TCP通信代码中的客户端可以同时配置多个实例。代码扩展还可以实现一个客户端发送后其余客户端接收(类似群聊),配置线程池以提高效率。其余实现代码放在了gitee上,需要的可以自行提取gitee仓库。