java - 使用 java scoket 在接收到的文件中获取额外的字节
问题描述
我已经使用 java socket 实现了一个文件传输程序。在这个程序中,从客户端发送一个文件,然后将其下载到服务器中。该程序几乎可以正常工作,但问题是接收到的字节长度总是大于从客户端发送的字节长度。例如,我从客户端发送了 678888589 字节,但是当我在服务器检查接收到的文件的长度时,我得到了 678925260 字节。出于这个原因,我在服务器端得到了不同的校验和。
这是我的代码:客户端类:
public class Client
{
final static int ServerPort = 1234;
public static final int BUFFER_SIZE = 1024 * 50;
private static byte[] buffer;
public static void main(String args[]) throws UnknownHostException, IOException
{
Scanner scn = new Scanner(System.in);
buffer = new byte[BUFFER_SIZE];
for(int i=0;i<8;i++) {
Socket s1 = new Socket(ip, ServerPort);
DataOutputStream dos1 = new DataOutputStream(s1.getOutputStream());
SendMessage message = new SendMessage(s1, "test.mp4",dos1);
Thread t = new Thread(message);
System.out.println("Adding this client to active client list");
t.start();
}
}
}
class SendMessage implements Runnable{
String file_name;
Socket s;
public final int BUFFER_SIZE = 1024 * 50;
private byte[] buffer;
DataOutputStream dos;
public SendMessage(Socket sc,String file_name,DataOutputStream dos) {
this.file_name = file_name;
this.s=sc;
buffer = new byte[BUFFER_SIZE];
this.dos = dos;
}
@Override
public void run() {
File file = new File(file_name);
try {
sendFile(file, dos);
dos.close();
while(true) {
}
} catch (IOException e1) {
e1.printStackTrace();
}
}
public void sendFile(File file, DataOutputStream dos) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE+1];
if(dos!=null&&file.exists()&&file.isFile())
{
FileInputStream input = new FileInputStream(file);
dos.writeLong(file.length());
System.out.println(file.getAbsolutePath());
int read = 0;
int totalLength = 0;
while ((read = input.read(buffer)) != -1) {
dos.write(buffer);
totalLength +=read;
System.out.println("length "+read);
}
input.close();
System.out.println("File successfully sent! "+totalLength);
}
}
}
服务器类
// Server class
public class Server
{
// Vector to store active clients
static Vector<ClientHandler> ar = new Vector<>();
// counter for clients
static int i = 0;
public static void main(String[] args) throws IOException
{
// server is listening on port 1234
ServerSocket ss = new ServerSocket(1234);
Socket s;
// running infinite loop for getting
// client request
while (true)
{
// Accept the incoming request
s = ss.accept();
System.out.println("New client request received : " + s);
// obtain input and output streams
DataInputStream dis = new DataInputStream(s.getInputStream());
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
System.out.println("Creating a new handler for this client...");
// Create a new handler object for handling this request.
ClientHandler mtch = new ClientHandler(s,"client " + i, dis, dos);
// Create a new Thread with this object.
Thread t = new Thread(mtch);
System.out.println("Adding this client to active client list");
// add this client to active clients list
ar.add(mtch);
// start the thread.
t.start();
// increment i for new client.
// i is used for naming only, and can be replaced
// by any naming scheme
i++;
}
}
}
// ClientHandler class
class ClientHandler implements Runnable
{
Scanner scn = new Scanner(System.in);
private String name;
final DataInputStream dis;
final DataOutputStream dos;
Socket s;
boolean isloggedin;
public static final int BUFFER_SIZE = 1024*50;
private byte[] buffer;
// constructor
public ClientHandler(Socket s, String name,
DataInputStream dis, DataOutputStream dos) {
this.dis = dis;
this.dos = dos;
this.name = name;
this.s = s;
this.isloggedin=true;
buffer = new byte[BUFFER_SIZE];
}
@Override
public void run() {
String received;
BufferedOutputStream out = null;
String outputFile = "out_"+this.name+".mp4";
BufferedInputStream in = null;
try {
in = new BufferedInputStream(s.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
out = new BufferedOutputStream(new FileOutputStream(outputFile));
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// while (true)
// {
try
{
long length = -1;
length = dis.readLong();
if(length!=-1)System.out.println("length "+length);
// String checkSum = dis.readUTF();
// System.out.println(checkSum);
int len=0;
long totalLength = 0;
// int len = 0;
while ((len = in.read(buffer,0,BUFFER_SIZE)) > 0) {
out.write(buffer, 0, len);
totalLength+=len;
// if(len<BUFFER_SIZE)break;
// System.out.println("length "+len);
if(len<=0)break;
}
File file = new File(outputFile);
System.out.println("total length1 "+totalLength+ " dif "+(totalLength-length));
System.out.println("output length "+file.length());
} catch (IOException e) {
e.printStackTrace();
}
}
private static String checksum(String filepath, MessageDigest md) throws IOException {
// file hashing with DigestInputStream
try (DigestInputStream dis = new DigestInputStream(new FileInputStream(filepath), md)) {
while (dis.read() != -1) ; //empty loop to clear the data
md = dis.getMessageDigest();
}
// bytes to hex
StringBuilder result = new StringBuilder();
for (byte b : md.digest()) {
result.append(String.format("%02x", b));
}
return result.toString();
}
}
如果有人能告诉我我做错了什么,那就太好了。另外,如何验证服务器端的校验和。另一个问题是服务器端代码在此块中被阻止。
while ((len = in.read(buffer,0,BUFFER_SIZE)) > 0) {
out.write(buffer, 0, len);
System.out.println("length "+len);
if(len<=0)break;
}
除非客户端断开连接,否则它不能中断循环。尽管文件已正确接收。
问候。
解决方案
您在客户端代码上犯了一个小错误。您正在写出完整的缓冲区,而不是从文件中读取的内容。
while ((read = input.read(buffer)) != -1) {
dos.write(buffer,0,read);
totalLength += read;
System.out.println("length " + read);
}
推荐阅读
- python - 当我在 python 函数中传递可变参数时,第一次更新它返回预期的输出但不同的参数是一个意外的 O./P
- laravel - 不显示具有特定 id 的事件(id 数组)
- python - re.escape 的正则表达式匹配问题
- visual-studio-code - vcpkg 在 VS 代码中安装
- python - 如何使用 Azure 数据工厂活动实现一些 python 函数?
- django - 使用自定义身份验证时如何为 Firebase 编写安全规则?
- python - Python 中的导入:一些问题
- python - 为什么 Cloudinary 上的图像不显示?
- python - Python 列表按键查找值
- vue.js - 在vue中成功保存数据时的成功消息