目录
需求
服务端实现
客户端实现
测试
需求
可试着根据java编程课所学到的java socket编程技术,尝试编写一个基于 TCP 的单线程文件收发程序,需满足:
服务端程序预先定义好需要发送的文件并等待客户端的连接。
客户端连接成功后,服务端将文件发送给客户端,客户端将文件保存到本地。
需要在同一个 TCP 连接内发送多个文件,不限制文件的类型和大小(操作系统支持的前提下)。
服务端实现
服务端Service实现
首先使用在端口6666创建一个ServerSocket类对象,使用accept方法监听6666端口的入站连接,如图12所示。
图12
创建DataOutputStream输出流对象,将文件的数量、各个文件的名字以及各个文件的大小写入输出流,如图13所示。
图13
创建BufferOutputStream输出流对象,将文件以字节流的方式发送出去,如图14所示。
图14
Java完整代码
使用Socket建立了一个服务器,并向连接上该服务器的客户端发送特定文件夹中的文件信息和文件内容。
首先,通过创建ServerSocket对象并指定端口号6666,该服务器将在该端口上监听客户端的连接请求。
接下来,通过调用serverSocket.accept()
方法,服务器将等待客户端的连接,并一旦有客户端连接上,就会返回一个表示客户端连接的Socket对象。
然后,定义了一个File对象file,指定了要发送文件的文件夹路径。
通过调用file.listFiles()
方法,获取文件夹中的所有文件,并保存在一个File数组files中。
接下来,通过创建DataOutputStream对象data,并使用socket的输出流进行初始化。之后,通过data.writeInt(files.length)
将文件数量写入输出流,告诉客户端接下来要传送的文件数量。
然后,通过循环遍历files数组,依次将每个文件名和文件长度写入输出流,使用data.writeUTF(files[i].getName())
和data.writeLong(files[i].length())
完成。
接下来,创建了一个BufferedOutputStream对象output,利用socket的输出流进行初始化。然后,再次循环遍历files数组,对每一个文件创建一个BufferedInputStream对象input,读取文件的内容,并将内容通过output写入到socket的输出流中,实现文件的传输。
最后,关闭output、socket和serverSocket,释放相关资源。
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Service {
public static void main(String[] args)throws Exception {
ServerSocket serverSocket=new ServerSocket(6666);
Socket socket=serverSocket.accept();
File file=new File("C:\\Users\\Yezi\\Desktop\\互联网编程\\实验1\\Service");
File[] files=file.listFiles();
DataOutputStream data=new DataOutputStream(socket.getOutputStream());
data.writeInt(files.length);
for(int i=0;i<files.length;i++){
data.writeUTF(files[i].getName());
data.writeLong(files[i].length());
}
BufferedOutputStream output=new BufferedOutputStream(socket.getOutputStream());
for(int i=0;i<files.length;i++){
BufferedInputStream input=new BufferedInputStream(new FileInputStream("C:\\Users\\Yezi\\Desktop\\互联网编程\\实验1\\Service\\"+files[i].getName()));
int one=input.read();
while(one!=-1){
output.write(one);
one=input.read();
}
}
output.close();
socket.close();
serverSocket.close();
}
}
客户端实现
客户端Client实现
首先创建套接字并将其连接到本地IP地址的6666端口,创建DataInputStream输入流对象,准备接受字节流,如图15所示。
图15
接收文件数量、各个文件的名字以及各个文件的大小,如图16所示。
图16
创建BufferInputStream输入流对象,以字节流的方法接收各个文件,并保存在本地,如图17所示。
图17
Java完整代码
通过Socket连接到指定的服务器,并接收服务器发送过来的文件信息和文件内容,保存到本地。
首先,通过创建Socket对象并指定服务器的IP地址(InetAddress.getLocalHost()
)和端口号6666,客户端将连接到该地址上的服务器。
接下来,创建DataInputStream对象data,并使用socket的输入流进行初始化。然后,通过data.readInt()
读取服务器发送过来的文件数量。
接着,定义了两个数组fileName和fileLength,用于保存每个文件的文件名和文件长度。
通过循环遍历文件数量fileNumber,分别从输入流中读取文件名和文件长度,并将其保存在对应的数组中,使用fileName[i]=data.readUTF()
和fileLength[i]=data.readLong()
完成。
然后,创建了一个BufferedInputStream对象input,利用socket的输入流进行初始化。然后,再次循环遍历文件数量fileNumber,在每一轮循环中,先创建一个BufferedOutputStream对象output,使用FileOutputStream将其绑定到指定路径的文件上。
通过循环读取input中的每一个字节,并将其写入到output中,实现文件的接收和保存。
最后,关闭output、socket的输出流(通过socket.shutdownOutput()
)以及socket,释放相关资源。
import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
public class Client {
public static void main(String[] args)throws Exception {
Socket socket=new Socket(InetAddress.getLocalHost(),6666);
DataInputStream data=new DataInputStream(socket.getInputStream());
int fileNumber=data.readInt();
String[] fileName=new String[fileNumber];
long[] fileLength=new long[fileNumber];
for(int i=0;i<fileNumber;i++){
fileName[i]=data.readUTF();
fileLength[i]=data.readLong();
}
BufferedInputStream input=new BufferedInputStream(socket.getInputStream());
for(int i=0;i<fileNumber;i++){
BufferedOutputStream output=new BufferedOutputStream(new FileOutputStream("C:\\Users\\Yezi\\Desktop\\互联网编程\\实验1\\Client\\"+fileName[i]));
for(long j=0;j<fileLength[i];j++){
int one=input.read();
output.write(one);
}
output.close();
}
socket.shutdownOutput();
socket.close();
}
}
测试
准备好多个文件,包括不同类型的图片、excel表格文件、ppt文件,准备发送,如图18所示。
图18
运行Service程序和Client程序,在Client文件查看测试结果,所有文件成功传送,测试成功,如图19所示。
图19