开发者

server sends file to clients java

开发者 https://www.devze.com 2023-03-01 09:51 出处:网络
I have a server and multiple clients and i am trying to make the server-thread send a file to the all connected clients at the same time.The weird thing is,sometimes the files are written correctly an

I have a server and multiple clients and i am trying to make the server-thread send a file to the all connected clients at the same time.The weird thing is,sometimes the files are written correctly and sometimes the laptop makes noise 开发者_Python百科and the files are written in the console and no files are created.I don`t do any changes in the code between the trials.Could anyone help me about that? Thanks in advance.Here is the sending server-thread code

try
{   
    out.println("AcceptFile,");
    FileInputStream fis = new FileInputStream(fn);
    byte[] buffer = new byte[fis.available()];
    fis.read(buffer);
    ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()) ;
    oos.writeObject(buffer);
    oos.flush();
}
catch(Exception c)
{
    System.err.println("exc" + c);
}

Here is the Client-thread receiving

try
{
    ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
                    byte[] buffer = (byte[])ois.readObject();
                    String pic="copy"+studId+".pdf";
                    System.out.println(pic);
                    FileOutputStream fos = new FileOutputStream(pic);
                    fos.write(buffer);  
                    fos.flush();
                    fos.close();    
}
catch(Exception e)
{
    System.out.println("Exception writing");
}


This is a recurring problem I see over and over. You have no guarantees that the underlying socket will not flush when you don't want it to. If it does, then the client can get a partial Object, and ObjectInputStream will throw an Exception.

The way to deal with it is to have the server write the Object to an intermediate byte[] via a ByteArrayOutputStream. You then send a simple header describing the length of the bytes to follow, followed by the contents of the byte[] (flushing after each write). On the client side, you do the reverse of this: read the simple header so you know how many bytes to expect, then read into a byte[] via a ByteArrayInputStream, and from there you can read into a ObjectInputStream. Of course, since you're just writing to a file anyway, you could skip the ObjectInputStream on the client side and just directly write the byte[] to a file.

import java.io.*;

public class junk extends ClassLoader {


  public static void main(String[] args) throws Exception {
    new junk();
  }

  public void marshal(OutputStream socketOutputStream, Object obj) 
    throws Exception 
  {

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(bos);

    oos.writeObject(obj);

    byte[] bytes = bos.toByteArray();

    DataOutputStream dos = new DataOutputStream(socketOutputStream);

    // header
    dos.writeInt(bytes.length);
    dos.flush();

    dos.write(bytes);
    dos.flush();
  }

  public Object unmarshal(InputStream socketInputStream) throws Exception {

    DataInputStream dis = new DataInputStream(socketInputStream);

    int numToRead = dis.readInt();

    byte[] bytes = new byte[numToRead];

    dis.readFully(bytes);

    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);

    ObjectInputStream ois = new ObjectInputStream(bis);

    return ois.readObject();

  }

}
0

精彩评论

暂无评论...
验证码 换一张
取 消