JavaSE——网络编程

news/2025/1/13 1:12:14/

一、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.ppmy.cn/news/1562663.html

相关文章

用c实现C++类(八股)

在 C 语言中,虽然没有内建的面向对象编程(OOP)特性(如封装、继承、多态),但通过一些编程技巧,我们仍然可以模拟实现这些概念。下面将用通俗易懂的方式,逐步介绍如何在 C 中实现封装、…

C#中简单Socket编程

引言 Socket编程是网络编程的基础,通过Socket编程,可以实现计算机之间的通信。本文将介绍如何在C#中进行简单的Socket编程,包括服务器端和客户端的实现。示例将展示TCP连接的基本操作,适用于理解网络通信的基本概念和实现方法。 …

计算机网络——网络层-IP地址

一、IP 地址及其表示方法 • 我们把整个因特网看成为一个单一的、抽象的网络。IP 地址就是给每个连接在因特网上的主机(或路由器)分配一个在全世界范围是唯一的 32 位的标识符。 • IP 地址现在由因特网名字与号码指派公司ICANN (Internet Corporation f…

机器学习实战——K-均值聚类算法:原理与应用

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​​​​ ​​​​​​​​​​​​ ​​​​​ 1. K-均值聚类算法的原理解释 ✨ ✨ 1.1 算法概述 K-均值(K-Means&#xff…

一分钟学会文心一言API如何接入,文心一言API接入教程

一、前期准备 注册百度智能云账号: 前往百度智能云官网注册一个账号。这是接入文心一言API的基础。 了解API接口: 在百度智能云开放平台中,找到文心一言API的详情页,了解提供的API接口类型(如云端API、移动端API、离线…

机器学习的基本原理和算法

机器学习的基本原理是通过从数据中学习模式和规律,以便能够对新数据进行预测或决策。其核心思想是通过训练算法来自动地从数据中学习,并根据学习到的模式和规律进行预测和决策。 机器学习基本原理的深化 数据驱动: 机器学习依赖于大量数据来…

【Linux】Linux常见指令(上)

个人主页~ 初识Linux 一、Linux基本命令1、ls指令2、pwd命令3、cd指令4、touch指令5、mkdir指令6、rmdir指令7、rm指令8、man指令9、cp指令10、mv命令 Linux是一个开源的、稳定的、安全的、灵活的操作系统,Linux下的操作都是通过指令来实现的 一、Linux基本命令 先…

Python之pygame学习绘制基本图形

pygame绘制 这次来说下怎么绘制基本的图形,如矩形,圆,圆弧等! pygame.draw.rect 画一个矩形 pygame.draw.polygon 绘制一个多边形 pygame.draw.circle 画一个圆圈 pygame.draw.ellipse 绘制一个椭圆 pygame.draw.arc 画…