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端退出");

 

 

 

 

 

 

 

 

 

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CompletableFuture // todo

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

RabbitMQ基本介绍及简单上手

(一)什么是MQ MQ(message queue)本质上是队列,满足先入先出,只不过队列中存放的内容是消息而已,那什么是消息呢? 消息可以是字符串,json也可以是一些复杂对象 我们应用场…

跟着逻辑先生学习FPGA-第六课 无源蜂鸣器发声实验

硬件平台:征战Pro开发板 软件平台:Vivado2018.3 仿真软件:Modelsim10.6d 文本编译器:Notepad 征战Pro开发板资料 链接:https://pan.baidu.com/s/1AIcnaGBpNLgFT8GG1yC-cA?pwdx3u8 提取码:x3u8 1 知识背景 1.1 蜂鸣器简介 蜂鸣…

TensorFlow Quantum快速编程(高级篇)

五、实战:量子分类器应用 5.1 数据准备 在实战构建量子分类器时,数据准备是基石环节。选用鸢尾花数据集,这一经典数据集在机器学习领域应用广泛,其涵盖了三种鸢尾花品种的样本,每个样本包含花萼长度、花萼宽度、花瓣长度、花瓣宽度四个特征。鉴于本次构建二分类量子分类…

Mysql进阶篇

一:存储引擎 二:索引 2.1 索引概述 索引(index)帮助mysql高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用&…

通过gradle发布aar或jar携带sources-jar到maven nexus

找了很久,没有找到满意的。终于找到一个好的办法。 gradle7.x适用。比以前的写法简洁。 发布传统的jar工程 比如okhttp,fastjson等项目,纯java工程。 直接创建新文件publish.gradle: apply plugin: maven-publishProperties properties …

ELK日志分析实战宝典之ElasticSearch从入门到服务器部署与应用

目录 ELK工作原理展示图 一、ElasticSearch介绍(数据搜索和分析) 1.1、特点 1.2、数据组织方式 1.3、特点和优势 1.3.1、分布式架构 1.3.2、强大的搜索功能 1.3.3、数据处理与分析 1.3.4、多数据类型支持 1.3.5、易用性与生态系统 1.3.6、高性…

2025年VGC大众汽车科技社招入职测评综合能力英语口语SHL历年真题汇总、考情分析

早在1978年,大众汽车集团就开始了与中国的联系。1984年,集团在华的第一家合资企业—上汽大众汽车有限公司奠基成立;1991年,一汽-大众汽车有限公司成立;2017年,大众汽车(安徽)有限公司…

嵌入式C语言:二维数组

目录 一、二维数组的定义 二、内存布局 2.1. 内存布局特点 2.2. 内存布局示例 2.2.1. 数组元素地址 2.2.2. 内存布局图(简化表示) 2.3. 初始化对内存布局的影响 三、访问二维数组元素 3.1. 常规下标访问方式 3.2. 通过指针访问 3.2.1. 指向数…

H2数据库在单元测试中的应用

H2数据库特征 用比较简洁的话来介绍h2数据库,就是一款轻量级的内存数据库,支持标准的SQL语法和JDBC API,工业领域中,一般会使用h2来进行单元测试。 这里贴一下h2数据库的主要特征 Very fast database engineOpen sourceWritten…

R语言在森林生态研究中的魔法:结构、功能与稳定性分析——发现数据背后的生态故事!

森林生态系统结构、功能与稳定性分析与可视化研究具有多方面的重要意义,具体如下: 一、理论意义 ●深化生态学理论 通过研究森林生态系统的结构、功能与稳定性,可以深化对生态系统基本理论的理解。例如,生物多样性与生态系统稳定性…

【C++经典例题】求1+2+3+...+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句

💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏: 期待您的关注 题目描述: 原题链接: 求123...n_牛客题霸_牛客网 (nowcoder.com) 解题思路: …

day01-HTML-CSS——基础标签样式表格标签表单标签

目录 此篇为简写笔记下端1-3为之前笔记(强迫症、保证文章连续性)完整版笔记代码模仿新浪新闻首页完成审核不通过发不出去HTMLCSS1 HTML1.1 介绍1.1.1 WebStrom中基本配置 1.2 快速入门1.3 基础标签1.3.1 标题标签1.3.2 hr标签1.3.3 字体标签1.3.4 换行标…

基于Springboot+Vue的仓库管理系统

开发一个基于Spring Boot和Vue的仓库管理系统涉及到前端和后端的开发。本文呢,给出一个简单的开发步骤指南,用于指导初入的新手小白如何开始构建这样一个系统,如果**你想直接学习全部内容,可以直接拉到文末哦。** 开始之前呢给小…

快速导入请求到postman

1.确定请求,右键复制为cURL(bash) 2.postman菜单栏Import-Raw text,粘贴复制的内容保存,请求添加成功

预训练语言模型——BERT

1.预训练思想 有了预训练就相当于模型在培养大学生做任务,不然模型初始化再做任务就像培养小学生 当前数据层面的瓶颈是能用于预训练的语料快被用完了 现在有一个重要方向是让机器自己来生成数据并做微调 1.1 预训练(Pre - training)vs. 传…

数字孪生电网有什么作用?实时云渲染技术又如何赋能智慧电网?

电网系统的结构比较复杂,传统运维模式主要是依赖传感器和人工巡检,难以全面监测管理。而数字孪生技术的应用将推动电网智能化、绿色化的高效转型。 智慧电网利用物理模型、现场测量数据和历史数据,结合云计算、物联网、大数据等技术&#xf…

MiniMind - 从0训练语言模型

文章目录 一、关于 MiniMind 📌项目包含 二、📌 Environment三、📌 Quick Start Test四、📌 Quick Start Train0、克隆项目代码1、环境安装2、如果你需要自己训练3、测试模型推理效果 五、📌 Data sources1、分词器&am…

EasyCVR视频汇聚平台如何配置webrtc播放地址?

EasyCVR安防监控视频系统采用先进的网络传输技术,支持高清视频的接入和传输,能够满足大规模、高并发的远程监控需求。平台支持多协议接入,能将接入到视频流转码为多格式进行分发,包括RTMP、RTSP、HTTP-FLV、WebSocket-FLV、HLS、W…

【GlobalMapper精品教程】093:将tif影像色彩映射表(调色板)转为RGB全彩模式

参考阅读:【ArcGIS微课1000例】0137:色彩映射表转为RGB全彩模式 文章目录 一、Globalmapper中显示模式二、ArcGIS中显示模式三、调色板转为RGB全彩模式四、注意事项一、Globalmapper中显示模式 Globalmapper中,将谷歌等多种来源在线影像下载到本地后,可能会遇到以下数据格…