先修
- 计算机网络:
所谓计算机网络,就是把分布在不同区域的计算机与专门的外部设备用通信线路相互连接成一个规模大,而且功能强的网络系统,从而使得计算机之间可以相互传递信息,共享数据,软件等资源
- 网络编程:
所谓网络编程,指的就是在同一个网络中不同机器之间的通信
- IP地址:
IP地址指的是互联网地址(Internet Protocol Address),是互联网设备与互联网之间的唯一标识,在同一个网段中,IP地址是唯一的
IP地址是数字型的,是一个32位的整数,通常将其分成4个8位的二进制数,每8位之间用圆点隔开,每个8位整数可以转换为一个0~255的十进制整数,例如:202.9.128.88
分为IPv4和IPv6
- IP地址分类:
A类:保留给政府机构:1.0.0.1 ~ 126.255.255.254
B类:分配给中型企业:128.1.0.1 ~ 191.255.255.254
C类:分配给任何需要的个人:192.0.0.1 ~ 223.255.255.254
D类:用于组播:224.0.0.1 ~ 239.255.255 254
E类:用于实验:240.0.0.1 ~ 255.255.255.254
回收地址:127.0.0.1,指本地机,一般用于测试使用
IP地址可以唯一的确定网络上的一个通信实体,但一个通信实体可以有多个通信程序同时提供网络服务,此时还需要使用端口
- 端口:
数据的发送和接收都需要通过端口出入计算机,端口号用于唯一标识通信实体上进行网络通讯的程序,同一台机器上不能两个程序占用同一个端口。
端口号的取值范围:0 ~ 65535
端口分类:
公认端口:0 ~ 1023
注册端口:1025 ~ 49151
动态或私有端口:1024 ~ 65535
常用端口:mysql:3306 oracle:1521 tomcat:8080
- 通信协议:
需要通信的设备之间需要实现相同的通信协议
网络分层:物理层,数据链路层,网络层,传输层,会话层,表示层,应用层
通信协议分类:
网络层IP协议:IPv4和IPv6,互联网协议
传输层协议:TCP和UDP
应用层协议:HTTP
相关类
- InetAddress:
java提供了InetAddress类来代表ip地址,是对ip地址的抽取和封装,有两个子类:Ine4Address、Inet6Address,分别表示IPv4和IPv6。
package practice.internet;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* prudence
* 2020/5/19 6:48 下午
*/
public class InterntTest {
public static void main(String[] args) {
System.out.println("==========================1==========================");
//1、获取主机名称和ip地址
InetAddress localHost = null;//返回本地主机
try {
localHost = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
System.out.println(localHost);//PrudencedeMacBook-Pro.local/192.168.31.61
System.out.println("==========================2==========================");
//2、获取ip地址的字符串表示形式
String hostAddress = localHost.getHostAddress();
System.out.println(hostAddress);//192.168.31.61
System.out.println("==========================3==========================");
//3、获取主机名
String hostName = localHost.getHostName();//获取此IP地址的主机名
System.out.println(hostName);//PrudencedeMacBook-Pro.local
System.out.println("==========================4==========================");
//4、根据主机名或者ip地址获取InetAddress对象
try {
InetAddress id1 = InetAddress.getByName("61.135.169.121");
System.out.println(id1);// /61.135.169.121
InetAddress id2 = InetAddress.getByName("www.baidu.com");
System.out.println(id2);//www.baidu.com/61.135.169.121
} catch (UnknownHostException e) {
e.printStackTrace();
}
System.out.println("==========================5==========================");
//5、根据主机或者ip地址获取所有InetAddress对象
try {
InetAddress[] arr = InetAddress.getAllByName("www.baidu.com");
for (InetAddress address : arr) {
System.out.println(address.toString());
System.out.println(address.getHostAddress());
System.out.println(address.getHostName());
System.out.println("-----------------------------------------");
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
运行结果:
- URLEncoder类和URLDecoder类:
URLEncoder类和URLDecoder类用于完成普通字符串和application/x-www-form-urlencoded MIME字符串之间的转换
package practice.internet;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.net.UnknownHostException;
/**
* prudence
* 2020/5/19 6:48 下午
*/
public class InterntTest {
public static void main(String[] args) {
try {
//URLEncoder:编码,将普通字符串转换为普通字符串
String s = URLEncoder.encode("Java开发指南", "utf-8");
System.out.println(s);
//URLDecoder:解码,将特殊中文字符转换为普通字符串
String decode = URLDecoder.decode(s, "utf-8");
System.out.println(decode);
//注意:编码和解码需要采用相同的字符集
String decodeErr = URLDecoder.decode(s, "GBK");
System.out.println(decodeErr);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
运行结果:
TCP编程
TCP(Transmission Control Protocol)传输控制协议,基于字节流的传输层通信协议
特点:a、安全的 b、面向链接的 c、点对点的全双工 d、传输数据大小限制,一旦连接建立,双方可以按统一的格式传输大的数据
- TCP的三次握手:
a、客户端向服务端发送一个请求
b、服务端收到请求后,回客户端一个响应
c、客户端收到服务端的响应后,回服务端一个确认信息
- Socket通信模型:
Socket和ServerSocket
- 客户端发送消息,服务端接收消息:
package practice.internet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* prudence
* 2020/5/20 1:43 上午
*/
public class Client {
public static void main(String[] args) {
//1、建立一个与服务器之间的连接
//创建一个Socket对象,就相当于完成了三次握手,建立了一个安全的连接
Socket socket = null;
try {
//创建一个流套接字并将其连接到指定的IP地址的指定端口号
socket = new Socket(InetAddress.getByName("192.168.31.61"), 7777);
} catch (IOException e) {
e.printStackTrace();
}
//2、将需要发送的数据写入到网络中
try {
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello 玛卡巴卡".getBytes());
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
//1、实例化一个ServerSocket对象
//创建绑定到特定端口的服务器套接字
serverSocket = new ServerSocket(7777);
//2、监听:获取连接到的客户端
System.out.println("等待服务端的连接");
//侦听并接受此套接字的连接,未连接成功之前,一直处于阻塞状态
Socket socket = serverSocket.accept();
System.out.println("连接成功");
//3、获取网络到内存的一个输入流
InputStream inputStream = socket.getInputStream();
//4、读取数据
byte[] arr = new byte[1024];
int len = inputStream.read(arr);
String message = new String(arr, 0, len);
//5、组织信息
String ipString = socket.getInetAddress().getHostAddress();
int port = socket.getPort();
System.out.println(ipString + ":" + port + "说你说:" + message);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
- 客户端发送消息,服务端回复消息:
package practice.internet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* prudence
* 2020/5/20 1:43 上午
*/
public class Client {
public static void main(String[] args) {
//1、建立一个与服务器之间的连接
//创建一个Socket对象,就相当于完成了三次握手,建立了一个安全的连接
Socket socket = null;
try {
//创建一个流套接字并将其连接到指定的IP地址的指定端口号
socket = new Socket(InetAddress.getByName("192.168.31.61"), 7777);
} catch (IOException e) {
e.printStackTrace();
}
try {
//2、将需要发送的数据写入到网络中
OutputStream outputStream = socket.getOutputStream();
//3、写入
outputStream.write("hello 玛卡巴卡".getBytes());
outputStream.flush();
//4、收取服务端发送来的消息
InputStream inputStream = socket.getInputStream();
byte[] arr = new byte[1024];
int len = inputStream.read(arr);
String message = new String(arr, 0, len);
System.out.println("来自服务端的回复:" + message);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Server {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
//1、实例化一个ServerSocket对象
//创建绑定到特定端口的服务器套接字
serverSocket = new ServerSocket(7777);
//2、监听:获取连接到的客户端
System.out.println("等待客户端的连接");
//侦听并接受此套接字的连接,未连接成功之前,一直处于阻塞状态
Socket socket = serverSocket.accept();
System.out.println("连接成功");
//3、获取网络到内存的一个输入流
InputStream inputStream = socket.getInputStream();
//4、读取数据
byte[] arr = new byte[1024];
int len = inputStream.read(arr);
String message = new String(arr, 0, len);
//5、组织信息
String ipString = socket.getInetAddress().getHostAddress();
int port = socket.getPort();
System.out.println(ipString + ":" + port + "说:" + message);
//6、服务端给客户端回复消息
OutputStream outputStream = socket.getOutputStream();
outputStream.write("hello,马拉丁大".getBytes());
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
- 客户端上传文件到服务端:
文件不区分类型(.txt .png .java)
package practice.internet;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* prudence
* 2020/5/20 8:31 下午
*/
public class ClientFile {
public static void main(String[] args) {
//1、建立一个与服务器之间的连接
//创建一个Socket对象,就相当于完成了三次握手,建立了一个安全的连接
Socket socket = null;
try {
//创建一个流套接字并将其连接到指定的IP地址的指定端口号
socket = new Socket(InetAddress.getByName("192.168.31.61"), 8888);
} catch (IOException e) {
e.printStackTrace();
}
try {
//2、输入流和输出流
//输入流:用来读取客户端磁盘上的图片文件
BufferedInputStream input = new BufferedInputStream(new FileInputStream(new File("/Users/prudence/Desktop/具体报文")));
//输出流:将图片写入到网络中
BufferedOutputStream output = new BufferedOutputStream(socket.getOutputStream());
//3、将读取到的数据写入
byte[] arr = new byte[1024];
int len = 0;
while ((len = input.read(arr)) != -1) {
output.write(arr, 0, len);
output.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ServerFile {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
//1、实例化一个ServerSocket对象
//创建绑定到特定端口的服务器套接字
serverSocket = new ServerSocket(8888);
//2、监听:获取连接到的客户端
System.out.println("等待客户端的连接");
//侦听并接受此套接字的连接,未连接成功之前,一直处于阻塞状态
Socket socket = serverSocket.accept();
System.out.println("连接成功");
//3、读取网络中的数据
//输入流:读取网络中的数据
BufferedInputStream input = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream(new File("/Users/prudence/Desktop/具体报文Copy")));
//4、读取和写入
byte[] arr = new byte[1024];
int len = 0;
while ((len = input.read(arr)) != -1){
output.write(arr, 0, len);
output.flush();
}
System.out.println("上传文件成功");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
- 客户端从服务端下载文件:
package practice.internet;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
/**
* prudence
* 2020/5/20 9:29 下午
*/
public class ClientDownLoadFile {
public static void main(String[] args) {
//1、建立一个与服务器之间的连接
//创建一个Socket对象,就相当于完成了三次握手,建立了一个安全的连接
Socket socket = null;
try {
//创建一个流套接字并将其连接到指定的IP地址的指定端口号
socket = new Socket(InetAddress.getByName("192.168.31.61"), 9999);
} catch (IOException e) {
e.printStackTrace();
}
try {
//2、给服务端发送消息,消息的内容就是你需要下载的文件
OutputStream output = socket.getOutputStream();
output.write("具体报文".getBytes());
output.flush();
//3、将读取出来的文件写入到客户端的磁盘中
InputStream input = socket.getInputStream();
FileOutputStream outputStream = new FileOutputStream(new File("/Users/prudence/Desktop/具体报文Copy"));
byte[] arr = new byte[1024];
int len = 0;
while ((len = input.read(arr)) != -1) {
outputStream.write(arr, 0, len);
outputStream.flush();
}
System.out.println("下载完成");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ServerDownloadFile {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
//1、实例化一个ServerSocket对象
//创建绑定到特定端口的服务器套接字
serverSocket = new ServerSocket(9999);
//2、监听:获取连接到的客户端
System.out.println("等待客户端的连接");
//侦听并接受此套接字的连接,未连接成功之前,一直处于阻塞状态
Socket socket = serverSocket.accept();
System.out.println("连接成功");
//3、读取客户端发送来的消息
InputStream input = socket.getInputStream();
byte[] arr = new byte[1024];
int len = input.read(arr);
String s = new String(arr, 0, len);
System.out.println("客户端要下载的文件:"+s);
//4、在服务端的磁盘下查找是否存在指定的文件
File file = new File("/Users/prudence/Desktop", s);
//5、判断
if(file.exists()){
//6、先从服务端的磁盘中读取出来
FileInputStream inputStream = new FileInputStream(file);
//7、将读取出来的文件写入到网络中
OutputStream outputStream = socket.getOutputStream();
byte[] arr1 = new byte[1024];
int len1 = 0;
while ((len1 = inputStream.read(arr)) != -1){
outputStream.write(arr, 0, len1);
outputStream.flush();
}
/**
* Connection reset:连接重置
* 出现的原因:
* a、如果服务端因为某种原因关闭,但是客户端仍然在访问服务端
* b、如果多个人同时访问同一个ip地址和端口的话
*
* 解决办法:
* 在ServerSocket服务端Socket类中shutdownOutput(),作用禁用输出流
*/
socket.shutdownOutput();
}else {
//给客户端一个响应:提示文件不存在
System.out.println("未找到指定资源");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
- 多个客户端和一个服务端通信:
package practice.internet;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* prudence
* 2020/5/20 10:22 下午
*/
public class Clients {
public static void main(String[] args) {
/**
* 1、客户端对象
* 2、通过客户端向服务端发送消息【socket.getOutputStream】
* 3、接收服务端回复的消息【socket.getInputStream】
* 4、借助于Scanner
* 5、循环的发送和接收消息【进行约定:bye/886则break出循环】
* 6、释放资源
*/
//1、构建客户端的对象
Socket client = null;
try {
client = new Socket("192.168.31.61", 65500);
//2、获取网络输入流和网络输出流
OutputStream outputStream = client.getOutputStream();
InputStream inputStream = client.getInputStream();
//3、从控制台进行获取数据
Scanner scanner = new Scanner(System.in);
//4、进行循环的发送和接收消息
while (true) {
System.out.print("客户端对服务端说:");
String message = scanner.nextLine();
//4.1 进行发送
outputStream.write(message.getBytes());
outputStream.flush();
//4.2 接收消息
byte[] arr = new byte[1024];
int len = inputStream.read(arr);
String reply = new String(arr, 0, len);
System.out.println("收到服务端的反馈:" + reply);
//4.3 约定
if (reply.equals("886") || reply.equals("bye") || reply.equals("再见")) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//5、释放资源
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Client2 {
public static void main(String[] args) {
/**
* 1、客户端对象
* 2、通过客户端向服务端发送消息【socket.getOutputStream】
* 3、接收服务端回复的消息【socket.getInputStream】
* 4、借助于Scanner
* 5、循环的发送和接收消息【进行约定:bye/886则break出循环】
* 6、释放资源
*/
//1、构建客户端的对象
Socket client = null;
try {
client = new Socket("192.168.31.61", 65500);
//2、获取网络输入流和网络输出流
OutputStream outputStream = client.getOutputStream();
InputStream inputStream = client.getInputStream();
//3、从控制台进行获取数据
Scanner scanner = new Scanner(System.in);
//4、进行循环的发送和接收消息
while (true) {
System.out.print("客户端对服务端说:");
String message = scanner.nextLine();
//4.1 进行发送
outputStream.write(message.getBytes());
outputStream.flush();
//4.2 接收消息
byte[] arr = new byte[1024];
int len = inputStream.read(arr);
String reply = new String(arr, 0, len);
System.out.println("收到服务端的反馈:" + reply);
//4.3 约定
if (reply.equals("886") || reply.equals("bye") || reply.equals("再见")) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//5、释放资源
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Server12s {
public static void main(String[] args) {
/**
* 1、创建服务端对象
* 2、通过循环,为不同的客户端进行服务
* 3、循环体内,创建线程
* 4、线程的执行体中,进行发送消息和接收消息的操作
* 读取客户端发送来的消息【socket.getInputStream】
* 回复给客户端的消息【socket.getOutputStream】
* 5、进行约定:何时停止循环
* 6、释放资源
*/
//1、创建服务端对象
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(65500);
//2、通过循环,为不同的客户端进行服务:循环体内,创建线程
while (true) {
//获取当前的线程对象
Socket client = serverSocket.accept();
ServerThread thread = new ServerThread(client);
thread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 4、线程的执行体中,进行发送消息和接收消息的操作
* 读取客户端发送来的消息【socket.getInputStream】
* 回复给客户端的消息【socket.getOutputStream】
*/
class ServerThread extends Thread {
//定义一个成员变量,就是当前连接到的客户端
private Socket client;
public ServerThread() {
}
public ServerThread(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
OutputStream outputStream = client.getOutputStream();
InputStream inputStream = client.getInputStream();
//3、从控制台获取数据
Scanner scanner = new Scanner(System.in);
//4、进行循环的发送和接收消息
while (true) {
//接收客户端发送来的消息
byte[] arr = new byte[1024];
int len = inputStream.read(arr);
String message = new String(arr, 0, len);
System.out.println("来自客户端的消息:" + message);
//回复消息
System.out.println("服务端对客户端说:");
String reply = scanner.nextLine();
outputStream.write(reply.getBytes());
outputStream.flush();
//约定
if (message.equals("886") || message.equals("bye") || message.equals("再见")) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行结果:
服务端和客户端都不应“多说”,会打乱程序运行步骤
- TCP实现登录注册:
package practice.internet;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
/**
* prudence
* 2020/5/22 5:46 下午
*/
public class ClientByTCP {
public void doRegister(String userName, String password) {
realAction(userName, password, "192.168.31.61", 6666);
}
public void doLogin(String userName, String password) {
realAction(userName, password, "192.168.31.61", 7777);
}
//将用户名和密码发送给服务端
private void realAction(String userName, String password, String ip, int port) {
Socket client = null;
try {
//1、实例化一个Socket对象
client = new Socket(ip, port);
//2、获取输出流
//缓冲字符流
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(client.getOutputStream()));
//3、写入数据
writer.write(userName + "," + password);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ServerByTCP {
private ServerSocket registerSocket;//用来注册
private ServerSocket loginSocket;//用来登录
//将每次需要注册的用户名和密码以键值对的形式存储到配置文件中,结合Properties使用
//实例化一个Properties对象
private Properties userList = new Properties();
//构造代码块
{
//同步配置文件中的内容
try {
userList.load(new BufferedInputStream(new FileInputStream(new File("/Users/prudence/Desktop/userList.properties"))));
} catch (IOException e) {
e.printStackTrace();
}
}
//开启服务
public void start() {
//开启注册服务
new Thread() {
@Override
public void run() {
startRegisterService();
}
}.start();
//开启登录服务
new Thread() {
@Override
public void run() {
startLoginService();
}
}.start();
}
//实现注册功能
private void startRegisterService() {
try {
//1、实例化一个ServerSocket对象
this.registerSocket = new ServerSocket(6666);
while (true) {
//2、获取连接到的客户端
Socket socket = this.registerSocket.accept();
System.out.println("注册功能连接到客户端:" + socket);
//3、获取客户端发送来的数据
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//4、读取
String string = reader.readLine();
System.out.println(string);
//5、解析用户名和密码
String[] arr = string.split(",");
//6、注册 arr[0]:用户名 arr[1]:密码
if (this.userList.containsKey(arr[0]) && this.userList.containsValue(arr[1])) {
System.out.println("该用户已经存在,无需注册");
} else {
//新增一个用户
this.userList.setProperty(arr[0], arr[1]);
//将用户名和密码同步到配置文件中进行持久化
this.userList.store(new BufferedOutputStream(new FileOutputStream(new File("/Users/prudence/Desktop/userList.properties"))), "add an user");
System.out.println("注册成功");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
this.registerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//实现登录功能
private void startLoginService() {
try {
//1、实例化一个ServerSocket对象
this.loginSocket = new ServerSocket(7777);
//2、获取连接到的客户端
Socket socket = this.loginSocket.accept();
System.out.println("登录功能连接到客户端:" + socket);
//3、获取客户端发送来的用户名和密码
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//4、读取
String string = reader.readLine();
System.out.println(string);
//5、解析用户名和密码
String[] arr = string.split(",");
//6、登录
if (this.userList.containsKey(arr[0])) {
if (arr[1].equals(this.userList.getProperty(arr[0]))) {
System.out.println("登录成功");
} else {
System.out.println("用户名/密码错误");
}
} else {
System.out.println("还未注册,请先注册");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class DemoTest{
public static void main(String[] args) {
new ServerByTCP().start();
ClientByTCP client = new ClientByTCP();
client.doRegister("玛卡巴卡","123456");
client.doRegister("集美们","123456");
client.doLogin("玛卡巴卡","123456");
}
}
运行结果:
UDP编程
User Datagram Protocal的简称,用户数据包协议,提供面向事务的简单不可靠信息传送服务
特点:a.不安全 b.无连接 c.效率高 d.UDP传输数据时是有大小限制的,每个被传输的数据报必须限定在 64KB 之内
- DatagramSocket 和 DatagramPacket:
package practice.internet;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.security.InvalidParameterException;
/**
* prudence
* 2020/5/22 8:33 下午
*/
public class Sender {
public static void main(String[] args) {
//端口号表示的是指定的接收方的端口号,而发送方的端口是由系统自动分配的
sendMessage("192.168.31.61", 6666, "hi,guy,this is your father");
}
/**
* 发送数据
*
* @param ip 指定接收方的ip地址
* @param port 指定接收方的端口号
* @param message 需要发送的信息
*/
public static void sendMessage(String ip, int port, String message) {
//1、实例化DatagramSocket的对象
DatagramSocket socket = null;//和流的使用相似,使用套接字完成之后需要关闭
try {
socket = new DatagramSocket();
//2、将需要发送的数据封装为数据包
DatagramPacket packet = new DatagramPacket(message.getBytes(), message.length(), InetAddress.getByName(ip), port);
//3、发送
socket.send(packet);//将数据写入网络的过程
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Receiver {
public static void main(String[] args) {
//1、实例化DatagramSocket的对象
//需要进行端口号绑定:由发送方发送来的端口号进行决定
DatagramSocket socket = null;
try {
//创建数据报套接字并将其绑定到本地主机上的指定端口
socket = new DatagramSocket(6666);
//2、将接收到的数据封装到数据包中
byte[] arr = new byte[1024];
//构造DatagramPacket,用来接收长度无length的数据包
DatagramPacket packet = new DatagramPacket(arr, arr.length);
System.out.println("等待接收数据~~~~~~");
//3、接收数据
socket.receive(packet);//将数据从网络中读取出来
//4、获取发送方的详细信息
byte[] message = packet.getData();//返回数据缓冲区
String result = new String(message, 0, message.length);
//获取发送方的ip地址
InetAddress address = packet.getAddress();
String ip = address.getHostAddress();
//获取消息是从发送方哪个端口发出来的
int port = packet.getPort();
System.out.println(ip + ":" + port + "说:" + result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果: