一、实验名称
UDP客户服务器即时通信程序
二、实验目的:
掌握基于SOCKET的网络编程方法。
基于JAVA语言,编写一个SOCKET的即时通信小程序
三、实验内容和要求
实验内容:
基于JAVA语言,编写一个SOCKET的即时通信小程序
实验平台:
Windows操作系统、Linux操作系统。
JAVA开发平台(不限)。
参考书籍:
《JAVA NETWORK PROGRAMMING》
四、实验环境
硬件环境:
cpu型号:11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz
主频内存型号:2.42 GHz
容量:32+512
软件环境:
操作系统版本号:22631.3296
软件及语言版本版本:IntelliJ IDEA Community Edition2023-JAVA-JDK17.0.5
五、程序设计结构及技术原理
1、socket概述
socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用已实现进程在网络中通信。
socket起源于UNIX,在Unix一切皆文件哲学的思想下,socket是一种"打开—读/写—关闭"模式的实现,服务器和客户端各自维护一个"文件",在建立连接打开后,可以向自己文件写入内容供对方读取或者读取对方内容,通讯结束时关闭文件。
2、基于socket技术的TCP通信流程
1)服务端(被动连接,需创建自己的地址信息)
创建一个套接字 ———socket()
绑定IP地址、端口等信息到socket上——bind()
监听套接字——listen()
等待客户端的连接请求——accept()
发送、接收数据——send()和recv(),或者read()和write()
关闭网络连接——close()
2)客户端
创建一个套接字——socket()
连接服务器——connect()
接收、发送数据——send()和recv(),或者read()和write()
关闭网络连接——close()
3、基于socket技术的TCP通信流程框图
4、基于socket技术的UDP通信流程
1)服务器(Server)流程主要分为下述6个部分。
(1)建立套接字文件描述符,使用函数socket(),生成套接字文件描述符。
(2)设置服务器IP地址和端口,初始化要绑定的网络地址结构。
(3)绑定IP地址、端口等信息,使用bind()函数,将套接字文件描述符和一个地址进行绑定。
(4)循环接收客户端的数据,使用recvfrom()函数接收客户端的网络数据。
(5)向客户端发送数据,使用sendto()函数向服务器主机发送数据。
(6)关闭套接字,使用close()函数释放资源。UDP协议的客户端流程
2)UDP协议的客户端流程分为5个部分。
(1)建立套接字文件描述符,socket();
(2)设置服务器IP地址和端口,struct sockaddr;
(3)向服务器发送数据,sendto();
(4)接收服务器的数据,recvfrom();
(5)关闭套接字,close()。
六、实验步骤
一、Java基于Socket的文件传输小程序原理:
文件传输通常涉及到套接字编程,这是一种在两个应用程序之间创建连接并交换数据的技术。在Java中,Socket编程主要涉及java.net.Socket和java.io包中的InputStream、OutputStream等类。基本步骤如下:
a. 服务器端(Server):
-
- 创建ServerSocket监听特定端口,等待客户端连接。
- 当客户端连接时,使用accept()方法接受连接请求,并创建一个新的Socket实例处理该连接。
- 使用OutputStream写入文件内容到客户端,FileInputStream读取本地文件。
- 客户端断开连接后,关闭流。
b. 客户端(Client):
-
- 创建Socket连接到服务器的指定地址和端口。
- 使用FileOutputStream从服务器接收文件,FileInputStream保存到本地。
- 断开连接后,关闭流。
- 引用OutputStream和InputStream:
- OutputStream是输出流,用于将数据发送到另一端,如向Socket发送文件内容。
- InputStream是输入流,用于接收来自另一端的数据,如从Socket接收文件内容。 在文件传输过程中,这两个类分别代表了数据的双向流动,它们提供了读写操作,使得服务器和客户端能够进行数据交换。
- Server和Client类的UML类图(简化版):
- Server类包含以下元素:
- 属性:ServerSocket serverSocket, Socket clientSocket, File fileToTransfer
- 方法:start(), acceptConnection(), sendFile(), closeConnection()
- Client类包含以下元素:
- 属性:Socket socket, File localFile, FileOutputStream outputStream, FileInputStream inputStream
- 方法:connect(), downloadFile(), closeConnection()
- Server类包含以下元素:
- handClientConnection方法分析(假设这个方法在服务器端):
- handClientConnection方法,是在服务器端处理客户端连接的处理逻辑:
二、程序类图
三、Client类(客户端)
1)创建Socket连接
客户端尝试通过Socket类建立连接到服务器。
2)文件操作
从控制台输入的内容,使用BufferedInputStream读取字节到Server传入控制器中。
3)数据传输
获取socket的输出流(OutputStream),将通信内容写入输出流,并确保数据已完全发送出去。
4)关闭资源
关闭输入流、输出流和socket,释放系统资源。
5)异常处理
使用try-catch块捕获可能出现的异常,打印堆栈跟踪以进行调试。
Client代码片
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket
("127.22.0.0", 12345); // 连接服务器
System.out.println("成功连接到服务器");// 输出信息到控制台
BufferedReader input = new BufferedReader// 从服务器获取输入流
(new InputStreamReader(socket.getInputStream()));
PrintWriter output = new PrintWriter// 向服务器发送消息的输出流
(socket.getOutputStream(), true);
BufferedReader reader = new BufferedReader// 从控制台获取输入流
(new InputStreamReader(System.in));
String message;
while (true) {
System.out.print("> ");// 控制台输出符号
message = reader.readLine(); // 从控制台读取输入的消息
output.println(message);// 发送控制台输入的消息给服务器
if(message.equalsIgnoreCase// 如果收到"exit"消息,停止循环
("exit")){
break;
}
String response = input.readLine();// 读取服务器发送的消息
System.out.println
("服务器: " + response); // 输出服务器发送的消息到控制台
}
input.close(); // 关闭输入流
output.close(); // 关闭输出流
socket.close();// 关闭套接字
} catch (IOException e) {
e.printStackTrace();// 捕获并打印异常信息
}
}
}
四、Server(服务器)
1)主分支(创建与监听)
ServerSocket serverSocket = new ServerSocket(12345);:创建一个服务器套接字,监听指定的端口(12345)等待客户端连接。
2)客户端连接处理
serverSocket.accept();:阻塞地等待客户端连接,并获取连接的Socket对象。
3)控制台交互
读取客户端输入、输出流:使用BufferedReader和PrintWriter处理输入和输出数据。
4)子分支或细节
循环读取输入消息并处理:while (true)内,不断读取客户端消息,如果等于"exit"则跳出循环。
5)监听控制台
监听控制台输入:通过System.in读取用户命令,用于构建响应。
输入“exit”退出程序;
Server代码片
public class Server {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket
(12345); // 创建ServerSocket
System.out.println
("服务器已启动,等待连接...");// 输出信息到控制台
Socket clientSocket = serverSocket.accept(); // 监听客户端连接
System.out.println
("客户端 " + clientSocket.getInetAddress() + " 已连接");
// 输出信息到控制台
BufferedReader input = new BufferedReader// 从客户端获取输入流
(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter output = new PrintWriter// 向客户端发送消息的输出流
(clientSocket.getOutputStream(), true);
BufferedReader reader = new BufferedReader
(new InputStreamReader(System.in));// 从控制台获取输入流
String message;
while (true) {
message = input.readLine();// 读取客户端发送的消息
if (message.equalsIgnoreCase("exit")) {
break;// 如果收到"exit"消息,停止循环
}
System.out.println("客户端: " + message);// 输出客户端发送的消息到控制台
System.out.print("> "); // 控制台输出符号
String response = reader.readLine(); // 从控制台读取输入的消息
output.println(response);// 发送控制台输入的消息给客户端
}
input.close();// 关闭输入流
output.close();// 关闭输出流
clientSocket.close(); // 关闭客户端套接字
serverSocket.close(); // 关闭服务器端套接字
} catch (IOException e) {
e.printStackTrace();// 捕获并打印异常信息
}
}
}
七、操作步骤
1)运行配置:
Jdk17.0.5,IntelliJ IDEA Community Edition2023
运行文件改为当前文件
2)运行Server类(服务器类)
等待服务器启动成功 /next
3)运行Client类(客户端)
连接服务器类(Server)
4)从客户端(Client)发送消息,即可在服务器端(Server)收到客户端(Client)的消息
5)服务器(Server)发送信息,客户端(Client)也能收到
6)测试控制台监听并“exit”退出程序
Client
Server
Client:输入“exit”程序终止
八、实验代码截图(IntelliJ IDEA Community Edition2023)
Client类:
Server类:
九、实验体会、质疑和建议
实验总结:
技术选型:
ServerSocket serverSocket = new ServerSocket(12345);:创建一个服务器套接字,监听指定的端口(12345)等待客户端连接。serverSocket.accept();:阻塞地等待客户端连接,并获取连接的Socket对象,NIO(非阻塞I/O)或通道(Channels)机制有助于提高性能。
程序结构:
Server
ServerSocket serverSocket = new ServerSocket
(12345); // 创建ServerSocket
Client
Socket socket = new Socket
("127.0.0.1", 12345); // 连接服务器
通常包括服务器端(Server)接收客户端请求,创建Socket连接,读取信息并发送到客户端;客户端(Client)则连接服务器。
文件传输:
BufferedReader input = new BufferedReader// 从客户端获取输入流
(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter output = new PrintWriter// 向客户端发送消息的输出流
(clientSocket.getOutputStream(), true);
通过字节流(InputStream/OutputStream)进行逐字节的数据传输
错误处理:
catch (IOException e) {
e.printStackTrace();// 捕获并打印异常信息
}
确保捕获并处理可能出现的异常,如网络中断、信息不存在等,并提供适当的错误反馈。
心得体会:
学习了Socket和ServerSocket的使用,知道如何创建和管理客户端和服务器套接字,以及如何通过它们进行双向通信;学会了如何使用Java的输入输出流来在网络连接上发送和接收数据。这包括使用BufferedReader和PrintWriter来简化字符流的读取和写入操作。
在网络编程中,可能会发生各种类型的异常,比如网络连接问题、IO异常等,学会如何捕获和处理这些异常非常重要;如果在服务器端需要同时处理多个客户端,可能需要使用多线程来实现并发通信,从而保证各个客户端的服务质量。设计通信协议是必要的,可以使用一些简单的协议来定义消息格式和通信规则,以便客户端和服务器能够正确地解析和处理消息。在真实的应用中,安全性是至关重要的,比如考虑到加密通信、身份验证等安全问题。
总的来说,基于Socket的即时通信小程序是一个很好的项目,可以让我了解到Java网络编程的基本原理并且提升实际动手能力。当然,实际生产环境中的网络应用可能更加复杂,但这样的小程序能为我打下一定的基础。