我用ServerSocket传送一组byte[]到client端,一共是86个字节,但是到client端后,只接收到82个字节, 后来,我分把server端传送的byte[]和client端接收的byte[]当成int型打印出来,发现丢失的字节是前四个,分别为-84,-19,0,5,原来我以为是client端接收的方式不当,后来发现,无论用BufferedInputStream或DataInputStream来包装输入流,都一样会有丢失的情况,请问这是什么原因造的?怎么解决呢?

解决方案 »

  1.   

    好像如果让负数转化为byte后不好怎么恢复呢
      

  2.   

    hehe, 楼主能保证接收方没有别的代码在 read() 吗?
      

  3.   

    先讲意图,其实我是想通过ServerSocket来传一个对象给Client,然后在Client端把对象还原,我以前在项目中已经用开源项目hessian来做到传送对象,由于近期在补基础,所以想自己来写一个,原理是先把一个对象通过ObjectOutputStream写在一个临时的文件中,然后用FileInputStream读取,再通过Socket把FileInputStream读到的字节一个个传过去,然后在Client端用ObjectInputStream还原。________________Server端_________________________________-package shuffle;import java.io.BufferedOutputStream;
    import java.io.DataOutputStream;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;import sun.security.krb5.internal.bp;public class TServer implements Runnable
    {
        public void launch() throws Exception
        {   
         TBean bean=new TBean();
            bean.setId("111");
            bean.setName("terry");
            Objecter objer=new Objecter(bean);
            byte b[]=objer.objectToBytes(); 
    //这两行就是我写的Objecter,可以把Object对象变成byte[],代码在下面
        
         ServerSocket server=new ServerSocket(TTestSocket.PORT);
         System.out.println("Server is starting......");
        
         while(true)
         {
            Socket client=server.accept();
                OutputStream os=client.getOutputStream();
                if(os!=null)
                {
                 BufferedOutputStream bos=new BufferedOutputStream(os);
                 System.out.println("Server sended "+b.length+" bytes.");
    String sendedContent=new String(b,0,b.length);
    System.out.println(senedContent);
                 System.out.println("#################################");
                 for (int i = 0; i < b.length; i++)
    {
        System.out.print((int)b[i]);
        System.out.print(',');
    }
                 System.out.println('\n');
                 bos.write(b);
                 bos.flush();
                 os.close();
                 bos.close();
                }
                else
                {
                 System.out.println("disconnect....");
                }     os.close();
         client.close();
         }
        }
        
        public void run()
        {
         try
    {
      launch();

         catch (Exception e)
    {
      e.printStackTrace();
    }
        }
    }
    -----------------Client---------------------------------package shuffle;import java.io.BufferedInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.ObjectInputStream;
    import java.net.Socket;public class TClient implements Runnable
    {
      public void launch() throws Exception
      { 
     System.out.println("Client is starting......");
     Socket client=new Socket("127.0.0.1",TTestSocket.PORT);
     InputStream is=client.getInputStream();
        
     //*************** BufferedInputStream的方式********************
     if(is!=null)
     {
     BufferedInputStream bis=new BufferedInputStream(is);
     ObjectInputStream ois=new ObjectInputStream(bis);
     byte b[]=new byte[bis.available()];
     bis.read(b);
     System.out.println("client received:"+b.length+" bytes");
     System.out.println("**********************************");
     for (int i = 0; i < b.length; i++)
     {
    System.out.print((int)b[i]);
    System.out.print(',');
     }
     System.out.println('\n');
     String msg=new String(b,0,b.length);
     System.out.println(msg);
    //  TBean bean=(TBean)ois.readObject();
    //  System.out.println("@@ name:"+bean.getName());
     bis.close();
     ois.close();
     
     FileOutputStream fos=new FileOutputStream("after.txt");
     fos.write(b);
     fos.flush();
     fos.close();
     }
     else
     {
     System.out.println("received null....");
     }
     is.close();
     client.close();
      }  public void run()
      {
    try
    {
       launch();
    //Thread.sleep(3000);

    catch (Exception e)
    {
    e.printStackTrace();
    }
      }
    }____________________Objecter________________________________package shuffle;import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.ObjectOutputStream;public class Objecter
    {
        Object obj;
    public Objecter(Object obj)
    {
    this.obj=obj;
    }

     public byte[] objectToBytes() throws Exception
     {
       byte b[]=null;
       File tmp=new File("tmp.txt");
           FileOutputStream fos=new FileOutputStream(tmp);
           BufferedOutputStream bos=new BufferedOutputStream(fos);
           ObjectOutputStream oos=new ObjectOutputStream(bos);
           
           oos.writeObject(obj);
           oos.flush();
           
           FileInputStream fis=new FileInputStream(tmp);
           BufferedInputStream bis=new BufferedInputStream(fis);
           b=new byte[bis.available()];
           bis.read(b);
           
           fos.close();
           bos.close();
           oos.close();
           fis.close();
           bis.close();
     
       return b;
     }
    }-----------------调用测试类------------------------------package shuffle;public class TTestSocket
    {
        public static int PORT=13564;
    public static void main(String[] args) throws Exception
    {
    Thread t1=new Thread(new TServer());
    Thread t2=new Thread(new TClient());

    t2.start();
    t1.start();
    }
    }
      

  4.   

    TBean bean=new TBean();
    这个对象要序列化
      

  5.   

    对了。。请问大家一个问题?怎么用JAVA进行对数组的操作?如:添加,修改,删除?我这几天碰到的JAVA面试题?大家有空帮我看看,最好写出代码。谢谢!
      

  6.   

    你的客户端程序既用了 BufferedInputStream,又用了 ObjectInputStream,搞不好会乱掉。你如果只用 BufferedInputStream 的话,还会丢 4 个字节吗?
      

  7.   

    我刚刚替你查了一下 ObjectInputStream 的源代码,发现在 ObjectInputStream ois=new ObjectInputStream(bis); 的时候,它已经从 bis 里面读掉 4 个字节了(两个 short, 0xACED, 0x0005,恰好是你说的 -84,-19,0,5)
      

  8.   

    自己做了测试确实是ObjectInputStream ois = new ObjectInputStream(bis);时候读掉了4个字节。为什么ObjectInputStream会这么做呢?
           首先传入ObjectInputStream构造器中的数据流对象不管是InputStream,BufferedInputStream,DataInputStream在他们传入到ObjectInputStrea以后自身的数据被修改,这样做可以防止这些数据流的read方法,如果在调用read方法的话会报java.io.EOFException的错误,因为数据流本身已经被修改了。这样可以尽可能的避免对象的修改,保持对象的正确性,一致性。我做了测试如果在TClient中得到TBean 的对象以后在调用Objecter对象把Client中的TBean还原成byte[]结果就和Server传过来得一样了。但前提示对象没有经过任何数据流的解析只是通过ObjectInputStream.readObject()得到的。