0

嗨,我正在尝试学习如何通过套接字发送文件,所以我编写了两个非常简单的 java 类,客户端和服务器,它们在这里

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;


public class Server {
    public static void main (String[] args)throws IOException{
        File f = new File("J:\\RepServer\\zebi.txt");
        if(!f.exists()){
            f.createNewFile();
            }
        //System.out.print(f.exists()+f.getName());
        ServerSocket ss = new ServerSocket(1000);
        Socket s = ss.accept();
        FileInputStream fileStream = new FileInputStream(f);
        ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
        oos.writeObject("Envoi Fichier|"+f.getName()+"|"+f.length());
        byte[] buffer = new byte[150000];
        long completed =0;
        while(completed <= f.length()){
            fileStream.read(buffer);
            oos.write(buffer);
            completed += 150000;
        }
        oos.writeObject("Envoi termine");
        fileStream.close();
    }
}

和客户端类

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;


public class Client {

/**
 * @param args
 * @throws ClassNotFoundException 
 */
public static void main(String[] args) throws IOException, ClassNotFoundException {
    new File("J:\\RepClient\\").mkdir();
    Socket s = new Socket("127.0.0.1",1000);
    ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
    String fileName = ((String)ois.readObject()).split("|")[1].trim();
    FileOutputStream fos = new FileOutputStream("J:\\RepClient\\"+fileName);
    byte[] buffer = new byte[200000];
    int byteLus = 0, compteur = 0;
    while(byteLus >= 0){
        byteLus = ois.read();
        if(byteLus >= 0){
            fos.write(buffer, 0, byteLus);
            compteur += byteLus;
            System.out.println("Le nombre de bytes lus est :"+byteLus);
        }
        if(byteLus < 1024){
            fos.flush();
            break;
        }
    }
}

}

所以我启动服务器,然后启动客户端,服务器将文件发送到客户端,客户端创建文件但为空,因为在服务器可以写入之前发生此异常。

Exception in thread "main" java.net.SocketException: Connection reset by peer: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(Unknown Source)
at java.net.SocketOutputStream.write(Unknown Source)
at java.io.ObjectOutputStream$BlockDataOutputStream.writeBlockHeader(Unknown Source)
at java.io.ObjectOutputStream$BlockDataOutputStream.write(Unknown Source)
at java.io.ObjectOutputStream.write(Unknown Source)
at Server.main(Server.java:25)

问题是我没有关闭客户端中的任何套接字或流。那么为什么连接关闭了?顺便说一句,冲洗在做什么?

4

2 回答 2

2

I think that the problem is in the way that you are trying to read data on the client side.

    byteLus = ois.read();

The read() method reads a single byte of data! Reference: the javadoc. But you seem to be assuming that it will (somehow) read a number of bytes into buffer. (Or something. The code is so wrong, it is not obvious what you think it should be doing!)


But frankly, there are lots of other problems with your code, both on the client and the server size. Some of the problems are as follows:

  • You should (probably) not be using read() or write(buffer) on an ObjectStream. You should be using readObject() and writeObject(obj) ... or using DataInputStream / DataOutputStream.

  • The way you are reading the file on the server side is broken. You are ignoring the result of the read call ... that tells you how many bytes you actually read into buffer. (You cannot assume that the only time you will get less that a full buffer is when you are near the end of the file. Some file types will regularly give you incomplete reads ... at least on some platforms.)

  • You are not closing oos or fos so there may be problems with data not being flushed.

  • The byteLus < 1024 test is inexplicable ... and wrong.

  • The logic of creating an empty file on the server if the file doesn't exist, escapes me (too). Why???

于 2013-07-28T01:27:39.220 回答
0

您的客户端在流结束时退出,退出进程会关闭套接字。与此同时,您的服务器仍在发送,因为您的发送和接收代码完全处于极端状态。@StephenC 指出,您的代码还有许多其他问题。Java中复制流的正确方法如下:

while ((count = in.read(buffer)) > 0)
{
   out.write(buffer, 0, count);
}

适用于任何大小大于 0 的缓冲区。两端的代码相同,输入和输出不同。允许语法变化:不允许语义变化。

于 2013-07-28T01:38:19.507 回答