首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java套接字同步行为

Java套接字同步行为
EN

Stack Overflow用户
提问于 2011-10-07 23:13:34
回答 1查看 2.4K关注 0票数 1

我尝试了很多方法来解决这个问题,但都没有成功,我也在这个论坛上寻找了一些信息,但都得到了相同的结果,所以我们开始吧。

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

服务器使用:

代码语言:javascript
复制
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();
}

在客户端:

代码语言:javascript
复制
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()随机返回一个非常高的数字,无论是负数还是正数(这意味着堆内存不足和其他异常)。

当然,这与同步有关,但我认为这两种方法之间的转换模式是正确的(可能是客户端太慢,服务器太快)。

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

非常感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-10-08 08:29:46

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7689231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档