Socket
什么是网络编程
- 在网络通信协议下,不同计算机上运行的程序,进行的数据传输.
- 应用场景:即时通信,网游对战.金融证券,国际贸易,邮件,等等.
- 不管是什么场景,都是计算机跟计算机之间通过网络进行数据传输.
- java中可以使用
java.net包下的技术轻松开发出常见的网络应用程序.
网络编程三要素
- ip:设备在网络中的地址,是唯一的标识.
- 端口号:应用程序在设备中唯一的标识.
- 协议:数据在网络中传输的规则,常见的协议有
UDP,TCP,HTTP,HTTPS,FTP.
ip
全称:Internet Protocol,是互联网协议地址,也称ip地址.是分配给上网设备的数字标签.上网设备在网络中的地址,是唯一的.
常见的分类:IPv4,IPv6
IPv4
- IPv4(Internet Protocol version4,互联网通信协议第四版)
- 采用32位地址长度,分成4组
IPv4的地址分类
- 公网地址(万维网使用)和私有地址(局域网使用).
- 192.168.开头的就是私有地址,范围即为192.168.0.0-192.168.255.255,专门为组织机构内部使用,以此节省IP
特殊IP地址
- 127.0.0.1也可以是localhost,是回送地址也称本地回环地址,也称本机IP,永远只会寻找当前所在的本机.
IPv6
- IPv6(Internet Protocol version6,互联网通信协议第六版)由于互联网的蓬勃发展,IP地址的需求量愈来愈大,而在IPv4模式下IP的总数是有限的.
- 采用128位地址长度,分成8组
InetAddress类
public class InetAddressTest {
public static void main(String[] args) throws UnknownHostException {
//确定主机名称的IP地址,主机名称可以是机器名称,也可以是IP地址
InetAddress byName = InetAddress.getByName("192.168.3.2");
System.out.println(byName);
//获取此IP的主机名
String hostName = byName.getHostName();
System.out.println(hostName);
//返回文本显示中的IP地址字符串
String ip = byName.getHostAddress();
System.out.println(ip);
}
}
端口号
- 应用程序在设备中唯一的标识.
- 端口号:由两个字节表示的整数,取值范围0-65535
- 其中0-1023之间的端口号用于一些知名网络服务或者应用.
- 我们自己使用1024以上的端口号就可以了
协议
- 计算机网络中,连接和通信的规则被称为网络通信协议
- OSI参考模型:世界互联协议标准,全球通信规范,单模型过于理想化,未能在因特网上进行广泛推广
- TCP/IP参考模型(或TCP/IP协议)事实上的国际标准.
UDP协议
单播
/**
* @ClassName SendMessage
* @Description : 发送消息
* @Author : ZG
* @Date: 2024-08-02 10:57
*/
public class SendMessage {
public static void main(String[] args) throws IOException {
//创建DatagramSocket对象
DatagramSocket datagramSocket = new DatagramSocket(9999);
//打包数据
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入内容!");
String nextLine = scanner.nextLine();
if ("886".equals(nextLine)) {
break;
}else {
byte[] bytes = nextLine.getBytes();
InetAddress address = InetAddress.getByName("127.0.0.1");
int port = 8888;
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length, address, port);
//发送数据
datagramSocket.send(datagramPacket);
}
}
//释放资源
datagramSocket.close();
}
}
/**
* @ClassName ReceiveMessage
* @Description : 接收消息方
* @Author : ZG
* @Date: 2024-08-02 11:04
*/
public class ReceiveMessage {
public static void main(String[] args) throws IOException {
//创建DatagramSocket对象
DatagramSocket datagramSocket = new DatagramSocket(8888);
//接收数据包
byte[] bytes = new byte[1024];
DatagramPacket datagramPacket = new DatagramPacket(bytes, bytes.length);
//解析数据包
while (true) {
datagramSocket.receive(datagramPacket);
byte[] data = datagramPacket.getData();
int length = datagramPacket.getLength();
int port = datagramPacket.getPort();
String message = new String(data, 0, length);
System.out.println("接收到来自" + port + "端口的数据:\r\n" + message);
}
}
}
组播
/**
* @ClassName SendMessage
* @Description : 组播发送消息
* @Author : ZG
* @Date: 2024-08-02 10:57
*/
public class SendMessage {
public static void main(String[] args) throws IOException {
//MulticastSocket
MulticastSocket ms = new MulticastSocket(9999);
//打包数据
byte[] bytes = "你好啊!".getBytes();
InetAddress address = InetAddress.getByName("224.0.0.1");
int port = 10000;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
//发送数据
ms.send(dp);
//释放资源
ms.close();
}
}
/**
* @ClassName ReceiveMessage
* @Description : 组播接收消息1
* @Author : ZG
* @Date: 2024-08-02 11:04
*/
public class ReceiveMessage01 {
public static void main(String[] args) throws IOException {
//创建MulticastSocket对象
MulticastSocket ms = new MulticastSocket(10000);
//将当前本机,添加到224.0.0.1这一组中
InetAddress address = InetAddress.getByName("224.0.0.1");
ms.joinGroup(address);
//接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//解析数据包
ms.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
InetAddress inetAddress = dp.getAddress();
String ip = inetAddress.getHostAddress();
String name = inetAddress.getHostName();
int port = dp.getPort();
String message = new String(data, 0, length);
System.out.println("接收到来自IP地址为:" + ip + "\r\n主机名为:" + name + "机器\r\n端口号为:" + port + "\r\n数据为:" + message);
//释放资源
ms.close();
}
}
/**
* @ClassName ReceiveMessage
* @Description : 组播接收消息1
* @Author : ZG
* @Date: 2024-08-02 11:04
*/
public class ReceiveMessage02 {
public static void main(String[] args) throws IOException {
//创建MulticastSocket对象
MulticastSocket ms = new MulticastSocket(10000);
//将当前本机,添加到224.0.0.1这一组中
InetAddress address = InetAddress.getByName("224.0.0.1");
ms.joinGroup(address);
//接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//解析数据包
ms.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
InetAddress inetAddress = dp.getAddress();
String ip = inetAddress.getHostAddress();
String name = inetAddress.getHostName();
int port = dp.getPort();
String message = new String(data, 0, length);
System.out.println("接收到来自IP地址为:" + ip + "\r\n主机名为:" + name + "机器\r\n端口号为:" + port + "\r\n数据为:" + message);
//释放资源
ms.close();
}
}
/**
* @ClassName ReceiveMessage
* @Description : 组播接收消息3
* @Author : ZG
* @Date: 2024-08-02 11:04
*/
public class ReceiveMessage03 {
public static void main(String[] args) throws IOException {
//创建MulticastSocket对象
MulticastSocket ms = new MulticastSocket(10000);
//将当前本机,添加到224.0.0.1这一组中
InetAddress address = InetAddress.getByName("224.0.0.1");
ms.joinGroup(address);
//接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//解析数据包
ms.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
InetAddress inetAddress = dp.getAddress();
String ip = inetAddress.getHostAddress();
String name = inetAddress.getHostName();
int port = dp.getPort();
String message = new String(data, 0, length);
System.out.println("接收到来自IP地址为:" + ip + "\r\n主机名为:" + name + "机器\r\n端口号为:" + port + "\r\n数据为:" + message);
//释放资源
ms.close();
}
}
广播
/**
* @ClassName SendMessage
* @Description : 广播发送消息
* @Author : ZG
* @Date: 2024-08-02 10:57
*/
public class SendMessage {
public static void main(String[] args) throws IOException {
//创建DatagramSocket对象
DatagramSocket ds = new DatagramSocket(9999);
//打包数据
byte[] bytes = "你好啊!!!".getBytes();
InetAddress address = InetAddress.getByName("255.255.255.255");
int port = 8888;
DatagramPacket dp = new DatagramPacket(bytes, bytes.length, address, port);
//发送数据
ds.send(dp);
//释放资源
ds.close();
}
}
/**
* @ClassName ReceiveMessage
* @Description : 广播接收消息
* @Author : ZG
* @Date: 2024-08-02 11:04
*/
public class ReceiveMessage {
public static void main(String[] args) throws IOException {
//创建DatagramSocket对象
DatagramSocket ds = new DatagramSocket(8888);
//接收数据包
byte[] bytes = new byte[1024];
DatagramPacket dp = new DatagramPacket(bytes, bytes.length);
//解析数据包
ds.receive(dp);
byte[] data = dp.getData();
int length = dp.getLength();
InetAddress inetAddress = dp.getAddress();
String ip = inetAddress.getHostAddress();
String name = inetAddress.getHostName();
int port = dp.getPort();
String message = new String(data, 0, length);
System.out.println("接收到来自IP地址为:" + ip + "\r\n主机名为:" + name + "机器\r\n端口号为:" + port + "\r\n数据为:" + message);
//释放资源
ds.close();
}
}
TCP协议
- TCP通信协议是一种可靠的网络协议,它在通信的两端建立一个Socket对象
- 通信之前要保证连接已经建立
- 通过Socket产生IO流来进行通信
/**
* @ClassName SendMessage
* @Description : 发送消息
* @Author : ZG
* @Date: 2024-08-02 10:57
*/
public class SendMessage {
public static void main(String[] args) throws IOException {
//TCP协议发送数据
//创建Socket对象,在创建对象的同时会连接服务端,连接不上的话会报错
Socket socket = new Socket("127.0.0.1", 8888);
//从连接通道中获取输出流
OutputStream os = socket.getOutputStream();
//解决中文乱码,使用转换流
OutputStreamWriter ow = new OutputStreamWriter(os);
//写出数据
ow.write("你好啊!");
//释放资源
ow.close();
socket.close();
}
}
/**
* @ClassName ReceiveMessage
* @Description : 接收消息方
* @Author : ZG
* @Date: 2024-08-02 11:04
*/
public class ReceiveMessage {
public static void main(String[] args) throws IOException {
//创建ServerSocket对象
ServerSocket serverSocket = new ServerSocket(8888);
//监听客户端连接
Socket accept = serverSocket.accept();
//从连接通道中获取输入流读取数据
InputStream is = accept.getInputStream();
//解决中文乱码,使用转换流
InputStreamReader ir = new InputStreamReader(is);
int read;
while ((read = ir.read()) != -1) {
System.out.print((char) read);
}
//释放资源
ir.close();
serverSocket.close();
}
}
三次握手
确保连接建立
- 客户端向服务端发送连接请求,等待服务器确认
- 服务端向客户端返回一个响应,告诉客户端收到了请求
- 客户端再次向服务端再次发送确认消息,连接建立
四次挥手
确保连接断开,数据处理完毕
-
客户端向服务端发送取消请求
-
服务端向客户端返回一个响应,表示收到了客户端的取消请求
-
服务端向客户端发出确认取消信息
-
客户端向服务端再次发送确认消息,连接取消