2011-10-07 41 views
1

我试图用很多方式解决问题,但没有成功,我也在此论坛中查找了信息,但结果相同,所以我们现在就去。Java套接字同步行为

我实际上在做一个服务器守护进程,它接受客户端请求,然后它(服务器)传输包含在特定文件夹中的所有文件。我将发布sendFileData(在服务器上)和receiveFileData(在客户端上)的代码。

服务器使用:

public static void sendFileData(File file, Socket socket) throws FileNotFoundException, IOException, SocketException { 
    byte[] auxiliar = new byte[8192]; 
    byte[] mybytearray = new byte[(int) file.length()]; 
    int longitud = mybytearray.length; 

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); 
    bis.read(mybytearray, 0, longitud); 
    DataOutputStream os = new DataOutputStream(socket.getOutputStream()); 
    int paquetes = longitud/8187; 
    int resto = longitud % 8187; 
    int i = 0; 
    while(i<paquetes){//The length goes on the first 4 bytes and the 5th tells if there are more packets to send (8192 bytes or less). 
     byte[] bytes = ByteBuffer.allocate(4).putInt(8187).array(); 
     auxiliar[0] = bytes[0]; 
     auxiliar[1] = bytes[1]; 
     auxiliar[2] = bytes[2]; 
     auxiliar[3] = bytes[3]; 
     auxiliar[4] = 1; 
     for(int j = 5; j < 8192; j++){ 
      auxiliar[j] = mybytearray[i*8187+(j-5)]; 
     } 
     os.write(auxiliar, 0, 8192); 

     i+=1; 
    } 
    if(resto > 0){ 
     byte[] bytes = ByteBuffer.allocate(4).putInt(resto).array(); 
     auxiliar[0] = bytes[0]; 
     auxiliar[1] = bytes[1]; 
     auxiliar[2] = bytes[2]; 
     auxiliar[3] = bytes[3]; 
     auxiliar[4] = 0; 
     for(int j = 5; j < resto+5; j++){ 
      auxiliar[j] = mybytearray[i*8187+(j-5)]; 
     } 
     os.write(auxiliar, 0, resto+5); 
    } 
    os.flush(); 
} 

而在客户端:

public static void receiveFileData(String nombreFichero, Socket s) throws IOException{ 
     File monitored = new File(nombreFichero); 
     if(monitored.exists() == false){ 
      monitored.createNewFile(); 
     } 
     byte[] mybytearray; 
     DataInputStream is = new DataInputStream(s.getInputStream()); 
     FileOutputStream fos = new FileOutputStream(monitored); 
     BufferedOutputStream bos = new BufferedOutputStream(fos); 
     int bytesRead = 0; 
     int hasNext = 1; 
     do { 
      bytesRead = is.readInt();//Leo longitud 
      try { 
       Thread.sleep(1);// HERE!!!! 
      } catch (InterruptedException e) { 
      } 
//   System.out.println("Bytes read "+bytesRead); 
      if(bytesRead <= 8187 && bytesRead > 0){ 
//    System.out.println("Bytes leídos "+bytesRead); 
       hasNext = is.readByte();//Leo si hay más datos por enviar 
       mybytearray = new byte[bytesRead]; 
       is.read(mybytearray); 
       if(monitored.exists()){ 
        synchronized(monitored){ 
         bos.write(mybytearray, 0, mybytearray.length); 
        } 
       } 
       mybytearray = null; 
      }else{ 
       System.out.println("Fuera de rango "+bytesRead); 
      } 
     }while(hasNext == 1); 
     bos.close(); 
     mybytearray = null; 
     System.out.println("Fichero recibido: "+monitored.getAbsolutePath()); 

    } 

在receiveFileData代码,如果我不把了Thread.sleep(1)或System.out的.println()或任何需要时间执行的用户,我没有以正确的方式在客户端上接收数据,因为readInt()会返回一个非常大的随机数或正数(这意味着Heap内存不足或其他异常) 。

确定这是关于同步,但我认为这两种方法之间的传输模式是正确的(也许客户端太慢,服务器速度太快)。

发生了什么?因为我不想放置Thread.sleep,所以我认为这不是很好的编程。

非常感谢!

+0

有多少个不同的线程可能调用receiveFileData()? sendFileData()同样的问题...另外,如果你只是在做一个文件 - >文件传输...为什么甚至混淆了除字节[]以外的任何东西?您需要在数据加载之前使用一个int来告诉另一方需要多少字节,但除此之外,只需发送原始字节! – claymore1977

+0

服务器只有一个正在侦听新连接的线程(accept())。当客户端尝试连接到服务器时,服务器会创建一个新的线程,该线程将分别管理客户端和服务器之间的数据流,然后继续监听。客户端只有一个线程。我想我试图发送完整的缓冲区文件的所有字节,但我认为这崩溃了(我必须检查,因为我现在不在家)。感谢您的回复 – cabreracanal

+0

这段代码将整个文件从一个地方传输到另一个地方吗? – claymore1977

回答

1

is.read(字节)不能保证填充提供的字节数组。您需要检查其返回值以查看读取了多少个字节或(更好)使用readFully()。

sleep()可能只是允许所有字节从套接字返回的时间。

+0

哦,非常感谢你,我会在星期一进行测试,如果没关系,我会检查你的答案是否被接受! – cabreracanal

+0

非常感谢你! readFully是解决方案,但我在发件人中也有问题:当文件长度为%8187 == 0时,对于最后一个包,hasNext = 1并且它应该为0.现在所有工作都正常! – cabreracanal