JavaSE——网络编程

一、InetAddress类

        InetAddress是Java中用于封装IP地址的类。

获取本机的InetAddress对象:

InetAddress localHost = InetAddress.getLocalHost();

根据指定的主机名获取InetAddress对象(比如说域名)

InetAddress host = InetAddress.getByName("www.baidu.com");

通过InetAddress对象获取对应的地址 

String hostAddress = host.getHostAddress();

通过InetAddress对象获取对应的主机名或者是域名

String hostAName = host.getHostName();

二、Socket 

        套接字(Socket)在开发网络应用程序中被广泛采用,以至于称为事实上的标准,它允许数据在两个Socket间通过IO传输。

流式套接字

        基于TCP协议,提供面向连接、可靠的数据传输服务。它保证数据的顺序性、完整性和可靠性,适用于对数据传输质量要求较高的场景,如文件传输、远程登录等。在Java中,使用Socket类来表示流式套接字。

数据报套接字

        基于UDP协议,提供无连接、不可靠的数据传输服务。它不保证数据的顺序性、完整性和可靠性,但传输速度快,适用于对实时性要求较高、对数据丢失不敏感的场景,如视频直播、在线游戏等。在Java中,使用DatagramScoket类和DatagramPacket类来实现数据报套接字通信。

        一般来讲,主动发起通信的应用程序属于客户端,等待通信请求的为服务端。

三、TCP网络通信编程

3.1TCP套接字通信原理

3.1.1服务端

  1. 创建ServerSocket:服务器端首先创建一个ServerSocket对象,并绑定到一个特定的端口,等待客户端的连接请求。

    ServerSocket ss = new ServerSocket(8888);

    表示服务器端在本地的 8888 端口上创建一个ServerSocket,准备接收客户端的连接。

  2. 监听连接请求:服务器端通过ServerSocket的accept方法监听客户端的连接请求。当没有客户端发起连接请求时,accept方法会阻塞等待,直到接收到一个连接请求,然后返回一个新的Socket对象,该Socket对象代表了服务器端与客户端之间的连接。

    Socket socket = ss.accept();

    表示服务器端接受了一个客户端的连接请求,并创建了一个新的Socket对象来与该客户端进行通信。

  3. 数据传输:可以使用socket.getInputStream()获取输入流,用于接收客户端发送的数据;使用socket.getOutStream()获取输出流,用于向客户端发送数据。

  4. 关闭连接:数据传输完成后,服务器端需要关闭与客户端的连接,释放资源。

3.1.2客户端

  1. 创建Socket:客户端创建一个Socket对象,并指定服务器端的IP地址和端口号,发起连接请求。
    Socket socket = new Socket(InetAddress.getLocalHost(),8888);
  2. 数据传输:连接建立后,客户端通过Socket对象的输入流和输出流与服务器端进行数据传输。与服务器端类似,客户端也可以使用socket.getInputStream和socket.OutputStream获取输入流和输出流,进行数据的读写操作。

  3. 关闭连接:数据传输完成后,客户端需要关闭连接,释放资源。

3.2TCP字节流编程实例

        要求客户端向服务端发送hello serve,服务端受到后返回hello client。

服务端:

//1. 在本机 的 9999 端口监听, 等待连接
// 细节: 要求在本机没有其它服务在监听 9999
// 细节:这个 ServerSocket 可以通过 accept() 返回多个 Socket[多个客户端连接服务器的并发]
ServerSocket ss = new ServerSocket(8888);
System.out.println("客户端监听中");

//如果没有客户端来连接,程序会阻塞等待连接
//如果有客户端连接则会返回socket对象,程序继续
Socket socket = ss.accept();
System.out.println("客户端IP" + socket.getInetAddress().getHostAddress());

//2.通过socket.getInputstream()读取客户端写入到数据通道的数据
InputStream inputstream = socket.getInputStream();

//IO读取
int readln = 0;
byte[] bytes = new byte[1024];
while((readln = inputstream.read(bytes)) != -1){
    System.out.println(new String(bytes,0,readln));
}
socket.shutdownInput();

//3.通过socket.getOutputStream()给客户端发送数据
OutputStream outputstream = socket.getOutputStream();
outputstream.write("hello client".getBytes());

//4.关闭流和socket
inputstream.close();
outputstream.close();
socket.close();
System.out.println("服务端退出");

客户端:

//1.连接服务端
Socket socket = new Socket(InetAddress.getLocalHost(),8888);
System.out.println("服务端IP" + socket.getInetAddress().getHostAddress());

//2.连接上后,生成Socket,通过socket.getOutputstream()得到与socket对象相关连的输出流对象
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = socket.getInputStream();
//通过输出流,写入数据到数据通道
outputStream.write("hello serve".getBytes());
//设计结束标记
socket.shutdownOutput();

//通过输入流,从通道中读取数据
byte[] buf = new byte[1024];
int readln = 0;
while ((readln = inputStream.read(buf)) != -1) {
    System.out.println(new String(buf, 0, readln));
}

//3.关闭流和对象
outputStream.close();
inputStream.close();
socket.close();
System.out.println("客户端已关闭");

3.3TCP文件上传 

3.3.1一个工具类

public class StreamUtils {
	/**
	 * 功能:将输入流转换成byte[]
	 * @param is
	 * @return
	 * @throws Exception
	 */
	public static byte[] streamToByteArray(InputStream is) throws Exception{
		ByteArrayOutputStream bos = new ByteArrayOutputStream();//创建输出流对象
		byte[] b = new byte[1024];
		int len;
		while((len=is.read(b))!=-1){
			bos.write(b, 0, len);	
		}
		byte[] array = bos.toByteArray();
		bos.close();
		return array;
	}
	/**
	 * 功能:将InputStream转换成String
	 * @param is
	 * @return
	 * @throws Exception
	 */
	
	public static String streamToString(InputStream is) throws Exception{
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder builder= new StringBuilder();
		String line;
		while((line=reader.readLine())!=null){ //当读取到 null时,就表示结束
			builder.append(line+"\r\n");
		}
		return builder.toString();
		
	}

}

        只需要知道这里的streamToByteArray方法将输入流的数据转换为byte[],streamToString方法将输入流转换为String。

3.3.2思路分析 

        先将磁盘上的图片转换成文件字节数组,通过Socket传输给服务端,服务端将得到的bytes文件写入到指定的路径中,向客户端回复 收到图片。

3.3.3服务端

//1.服务端在本机监听8888端口
ServerSocket ss = new ServerSocket(8888);
System.out.println("服务端在8888端口监听");

//2.等待连接
Socket socket = ss.accept();

//3.读取客户端发送的消息
//通过Socket得到输入流

BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] bytes = StreamUtils.streamToByteArray(bis);

//4.将得到的bytes数组写入到指定的路径中,就得到一个文件了
String str = "src\\my.jpg";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(str));
bos.write(bytes);
bos.close();

//向客户端回复收到图片
//通过socket获取到输出流(字符)
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bw.write("收到图片");
bw.flush();
socket.shutdownOutput();
//关闭其它资源
bw.close();
bis.close();
socket.close();
ss.close();

3.3.4客户端

//1.客户端连接服务端8888,得到Socket对象
Socket socket = new Socket(InetAddress.getLocalHost(),8888);

//创建读取磁盘文件的输入流
String filePath = "D:\\My.jpg";
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));

//byte就是filePath对应的字节数组
byte[] bytes = StreamUtils.streamToByteArray(bis);

//通过socket获取到输出流,将bytes数据发送给服务端
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(bytes);
bis.close();
socket.shutdownOutput();

//接收从服务端回复的消息
InputStream inputStream = socket.getInputStream();
//使用StreamUtils的方法直接将inputStream读取到的内容转成字符串
String s  = StreamUtils.streamToString(inputStream);
System.out.println(s);

//关闭相应的流
inputStream.close();
bos.close();
socket.close();

3.4TCP文件下载

3.4.1思路分析

         客户端将要下载的文件名传递给服务端,服务端返回对应文件,如果没有就返回默认。

3.4.2服务端

//1.监听 9999端口
ServerSocket serverSocket = new ServerSocket(9999);

//2.等待端口连接
Socket socket = serverSocket.accept();

//读取客户端发送要下载的文件名
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
int len = 0;
String downLoadFileName = "";
while ((len = inputStream.read(b)) != -1) {
    downLoadFileName += new String(b,0,len);
}
System.out.println("用户希望下载的文件名=" + downLoadFileName);

String resFileName = "";
if("高山流水".equals(downLoadFileName)){
    resFileName = "src\\高山流水.mp3";
}
else resFileName = "src\\无名.mp3";
//4.创建一个输入流,读取文件
BufferedInputStream bis =
        new BufferedInputStream(new FileInputStream(resFileName));

//5.使用工具类StreamUtils,读取文件到一个字节数组
byte[] buffer = StreamUtils.streamToByteArray(bis);

//6.得到Socket相关的输出流
BufferedOutputStream bos =
        new BufferedOutputStream(socket.getOutputStream());

//写入到数据通道,返回给客户端
bos.write(buffer);
socket.shutdownOutput();

//关闭相关资源
bos.close();
bis.close();
socket.close();
serverSocket.close();
System.out.println("服务端退出");

3.4.3客户端 

//1.接收用户输入,指定下载文件名
Scanner sc = new Scanner(System.in);
System.out.println("请指定下载文件名");
String downloadFileName = sc.nextLine();

//2.客户端连接服务端,准备发送
Socket socket = new Socket(InetAddress.getLocalHost(),9999);

//3.获取关联输出流
OutputStream os = socket.getOutputStream();
os.write(downloadFileName.getBytes());
//设置写入结束标志
socket.shutdownOutput();

//4.读取服务端返回的文件
BufferedInputStream bis =
        new BufferedInputStream(socket.getInputStream());
byte[] buffer = StreamUtils.streamToByteArray(bis);

//5.得到一个输出流,准备将bytes写入到磁盘文件
String filePath = "D:\\" + downloadFileName + ".mp3";
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
bos.write(buffer);

//关闭相关资源
bos.close();
bis.close();
os.close();
socket.close();
System.out.println("客户端已退出");

四、UDP网络通信编程

4.1 UDP通信原理

4.1.1发送端

  1. 创建DatagramSocket:发送端创建一个DatagramSocket对象,用于发送数据报。可以不指定端口号,让系统自动分配一个临时端口号;也可以指定一个端口号。
    DatagramSocket socket = new DatagramSocket();
    DatagramSocket socket = new DatagramSocket(8888);
  2. 创建DatagramPacket:发送端创建一个DatagramPacket对象,用于封装要发送的数据。需要指定数据内容、数据长度、接收端的 IP 地址和端口号。
    DatagramPacket packet = 
                        new DatagramPacket(data, data.length, InetAddress.getByName("server_ip"), 8888);
  3. 发送数据报:通过DatagramSocket的send(DatagramPacket p)方法发送数据报。
  4. 关闭DatagramSocket:数据发送完成后,发送端关闭DatagramSocket,释放资源。

4.1.2接收端

  1. 创建DatagramSocket:接收端创建一个DatagramSocket对象,并绑定到一个特定的端口上,用于接收数据报。
    DatagramSocket socket = new DatagramSocket(8888);
  2. 接收数据报:接收端通过DatagramSocket的reveive(Datagrampacket p)方法接收数据报。需要先创建一个Datagrampacket 对象作为接收容器,指定一个足够大的缓冲区来存储接收到的数据。
    byte[] buffer = new byte[1024];
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length); 
    socket.receive(packet);
  3. 处理数据:接收到数据报后,可以通过Datagrampacket对象获取数据内容、发送端的 IP 地址和端口号等信息。
    String receivedData = new String(packet.getData(), 0, packet.getLength()); 
    InetAddress senderAddress = packet.getAddress(); 
    int senderPort = packet.getPort();
  4. 关闭DatagramSocket:数据处理完成后,接收端关闭DatagramSocket,释放资源。

4.2UDP网络编程

4.2.1A端

//1.创建一个DatagramSocket对象,准备在9999端口接收数据
DatagramSocket socket = new DatagramSocket(9999);
//2.构建一个DatagramPacket对象,准备接收数据
//UDP协议一个数据包最大64k
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);

//3.调用接收方法,将通过网络传输的DatagramPacket对象
//  填充到packet对象中
//如果没有数据包发送到本机的9999端口,就会阻塞等待

socket.receive(packet);

//4.可以把packet拆包取出数据,并显示
int len = packet.getLength();//实际接收到的数据字节长度
byte[] data  = packet.getData();//接收到数据
String s = new String(data,0,len);
System.out.println(s);

//5.回复
byte[] buf2 = "好的".getBytes();
DatagramPacket packet2 = new DatagramPacket(buf2, buf2.length, InetAddress.getByName("192.168.31.130"),8888);
socket.send(packet2);
//关闭资源
socket.close();
System.out.println("A端退出");

4.2.2B端 

//1.创建DatagramSocket对象,准备在8888端口接收数据
DatagramSocket socket = new DatagramSocket(8888);

//2.将需要发送的数据封装到DatagramPacket对象中
byte[] data = "hello 明天吃火锅".getBytes();

//封装的DatagramPacket对象: data内容字节数组,data.length,主机IP,端口
DatagramPacket datagramPacket =
        new DatagramPacket(data, data.length, InetAddress.getByName("192.168.31.130"),9999);
socket.send(datagramPacket);

//接收A端的回复
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
socket.receive(receivePacket);
//拆包
int len = receivePacket.getLength();
byte[] receiveData2 = receivePacket.getData();
String s = new String(receiveData2,0,len);
System.out.println(s);
//关闭资源
socket.close();
System.out.println("B端退出");

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/952104.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

在Windows环境下搭建无人机模拟器

最近要开发无人机地面站,但是没有无人机,开发无人机对我来说也是大姑娘坐花轿——头一回。我们要用 MAVLink 和无人机之间通信,看了几天 MAVLink,还是不得劲儿,没有实物实在是不好弄,所以想先装一个无人机模…

安科瑞 Acrel-1000DP 分布式光伏监控系统在工业厂房分布式光伏发电项目中的应用

吕梦怡 18706162527 摘 要:常规能源以煤、石油、天然气为主,不仅资源有限,而且会造成严重的大气污染,开发清洁的可再生能源已经成为当今发展的重要任务,“节能优先,效率为本”的分布式发电能源符合社会发…

NAT 代理服务器

文章目录 1. NAT2. 内网穿透3. 内网打洞4. 代理服务器正向代理服务器反向代理服务器 5. DNS6. ICMP7.测试内网穿透 1. NAT 在ip协议章节,我们说报文转发给路由器时,由于私有IP地址不能出现在公网中,路由器会将报文源IP地址替换为路由器的WAN…

Python数据可视化-Pandas

文章目录 一. Pandas数据可视化简介二. Pandas 单变量可视化1. 柱状图2. 折线图3. 面积图4. 直方图5. 饼图 三. Pandas 双变量可视化1. 散点图2. 蜂巢图3. 堆叠图4. 折线图 一. Pandas数据可视化简介 pandas库是Python数据分析的核心库 它不仅可以加载和转换数据,还…

【NLP 18、新词发现和TF·IDF】

目录 一、新词发现 1.新词发现的衡量标准 ① 内部稳固 ② 外部多变 2.示例 ① 初始化类 NewWordDetect ② 加载语料信息,并进行统计 ③ 统计指定长度的词频及其左右邻居字符词频 ④ 计算熵 ⑤ 计算左右熵 ​编辑 ⑥ 统计词长总数 ⑦ 计算互信息 ⑧ 计算每个词…

【Elasticsearch】配置分片分配到指定节点

配置分片分配到指定节点 参考文章:https://www.elastic.co/guide/en/elasticsearch/reference/current/shard-allocation-filtering.html 两种方式:根据节点属性分配和根据节点名称分配。 测试环境 tar xvf elasticsearch-7.17.25-linux-x86_64.tar.gz…

1. Doris分布式环境搭建

一. 环境准备 本次测试集群采用3台机器hadoop1、hadoop2、hadoop3, Frontend和Backend部署在同一台机器上,Frontend部署3台组成高可用,Backend部署3个节点,组成3副本存储。 主机IP操作系统FrontendBackendhadoop1192.168.47.128Centos7Foll…

计算机毕业设计Python机器学习农作物健康识别系统 人工智能 图像识别 机器学习 大数据毕业设计 算法

温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…

gesp(C++四级)(11)洛谷:B4005:[GESP202406 四级] 黑白方块

gesp(C四级)(11)洛谷:B4005:[GESP202406 四级] 黑白方块 题目描述 小杨有一个 n n n 行 m m m 列的网格图,其中每个格子要么是白色,要么是黑色。对于网格图中的一个子矩形,小杨认为它是平衡的…

在Mac上使用 Docker 构建一个 noVNC 环境并运行 MyCobot

本文展示了Mycobot 280 M5 上的 Mycobot 280 M5 moveit2 模拟环境,以及详细介绍了使用 Docker 在 macOS(arm64)上构建 moveit2 环境的步骤。 一、引言 这篇文章主要内容是关于如何在 Ros2 环境中构建在 Mac 上模拟 Mycobot 280 M5 的环境。 …

c语言提供后端,提供页面显示跳转服务

后端代码: #define SERVER_IP_ADDR "0.0.0.0" // 服务器IP地址 #define SERVER_PORT 8080 // 服务器端口号 #define BACKLOG 10 #define BUF_SIZE 8192 #define OK 1 #define ERROR 0#include <stdio.h> #include <stdlib.h> #include <st…

AnaConda下载PyTorch慢的解决办法

使用Conda下载比较慢&#xff0c;改为pip下载 复制下载链接到迅雷下载 激活虚拟环境&#xff0c;安装whl&#xff0c;即可安装成功 pip install D:\openai.wiki\ChatGLM2-6B\torch-2.4.1cu121-cp38-cp38-win_amd64.whl

Sentinel服务保护 + Seata分布式事务

服务保护 【雪崩问题】微服务调用链路中某个服务&#xff0c;引起整个链路中所有微服务都不可用。 【原因】&#xff1a; 微服务相互调用&#xff0c;服务提供者出现故障。服务调用这没有做好异常处理&#xff0c;导致自身故障。调用链中所有服务级联失败&#xff0c;导致整个…

六、Angular 发送请求/ HttpClient 模块

一、应用 HttpClient 模块 angular/common/http 中的 HttpClient 类基于浏览器提供的 XMLHttpRequest 接口。要想使用 HtpClient 模块&#xff0c;就要先导入 Anqular 的 HttpClientModule。大多数 Web 应用程序都会在根模块 AppModule 中导入它。 编辑 src/app/app.module.ts…

CompletableFuture // todo

相比较所有代码都在主线程执行&#xff0c;使用Future的好处&#xff1a;利用服务器多核、并发的优势。 不足&#xff1a; 开启没有返回值的异步线程&#xff1a; 1、runAsync 使用lambda表达式&#xff1a; 开启有返回值的异步线程&#xff1a; 1、supplyAsync 异步任务中的…

css面试常考布局(圣杯布局、双飞翼布局、三栏布局、两栏布局、三角形)

两栏布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head> &…

arcgisPro加载天地图(CGCS2000)影像

1、注册天地图账号&#xff1b; 2、申请key&#xff1b; 3、添加WMTS服务器。 这里已经办好了前两步&#xff0c;下面详细介绍最后一步。 添加WMTS服务器。 在天地图网站&#xff0c;找到如下页面&#xff0c; 复制网址&#xff0c;如&#xff1a;http://t0.tianditu.gov.cn…

继承(7)

大家好&#xff0c;今天我们继续来学习一下继承的知识&#xff0c;这方面需要大家勤动脑才能理解&#xff0c;那么我们来看。 1.9 protected关键字 在类和对象章节中&#xff0c;为了实现封装特性,java中引入访向限定符,主要限定:类或者类中成员能否在类外和其他包中被访问. …

ModuleNotFoundError: No module named ‘podm.metrics‘报错等解决方法

ModuleNotFoundError: No module named podm.metrics’报错等解决方法 podm.metrics 在运行时报错&#xff1a; ModuleNotFoundError: No module named ‘podm.metrics’ 安装了podm后还是报错 解决方法&#xff1a; 查看安装位置 查看podm的安装位置&#xff0c;并打开到该…

HDFS异构存储和存储策略

一、HDFS异构存储类型 1.1 冷、热、温、冻数据 通常&#xff0c;公司或者组织总是有相当多的历史数据占用昂贵的存储空间。典型的数据使用模式是新传入的数据被应用程序大量使用&#xff0c;从而该数据被标记为"热"数据。随着时间的推移&#xff0c;存储的数据每周…