首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在发送文件后,流不会关闭

在发送文件后,流不会关闭
EN

Stack Overflow用户
提问于 2018-04-23 12:44:16
回答 4查看 156关注 0票数 3

对不起,我对溪流的理解正在慢慢地建立起来。

我无意中试图将一个音乐文件流到我的客户端,但是没有成功,所以我通过字节转移了整个文件,然后将它保存在客户端。问题是输入流仍在接收字节,因此不会脱离while循环(我想在其中播放歌曲)。

下面是我的客户端代码的一部分:

代码语言:javascript
运行
复制
//This is part of a task that carries this out (Part of a UI application)
@Override
protected Void call()
{
    try(Socket socket = new Socket(host,portNumber); 
        ObjectOutputStream toServer = new ObjectOutputStream(socket.getOutputStream());
        ObjectInputStream fromServer = new ObjectInputStream(socket.getInputStream()))
    {
        //Client requests a song from the server (song is a String)
        toServer.writeUTF(".Music."+song);
        toServer.flush();

        //Create a new file (tempSong is a string)
        File test = new File(tempSong);
        test.createNewFile();

        //New file writer
        BufferedOutputStream bOS = new BufferedOutputStream(new FileOutputStream(test));

        byte[] buffer = new byte[4096];
        int current;

        /** 
         * Read the bytes from the server and write the file
         * The file is written and I can play it (externally)
         * but the while loop doesn't break after writting the file
         */
        while ((current = fromServer.read(buffer)) > 0)
        {
            bOS.write(buffer, 0 , current);
        }

        System.out.println("Finished writing");

        bOS.close();

        /**
         * down here a method is ran to play the file
         * but it never happen because the task is still in the while loop
         */
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
    return null;
}

下面是服务器中读取消息并发送文件的服务器。

代码语言:javascript
运行
复制
/** This is part of a task and the main call area */
@Override
public Void call ()
{
    try
    {
        //Setup I/O
        toClient = new ObjectOutputStream(socket.getOutputStream());
        ObjectInputStream fromClient = new ObjectInputStream(socket.getInputStream());

        while(!socket.isClosed())
        {
            //If server has received a message
            if(fromClient.available() > 0)
            {
                //Reads message and objects from client
                String input = fromClient.readUTF();

                if (input.contains(".Music"))
                {
                    findMusic(input, toClient);
                }

                /**
                 * more else IFs
                 */
            }
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
    return null;
}
/**
 * this method is part of the task discussed above
 */
//The method that is called
private void findMusic(String input, ObjectOutputStream toClient)
{
    logoff();
    String[] names = input.split("[.]");
    clientManagerTemp.logger("Someone request song: " + names[2] + ".mp3");

    File musicFile = AudioUtil.getSoundFile("src/Resources/Songs/" + names[2]+ ".mp3");
    byte[] buffer = new byte[(int) musicFile.length()];

    try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(musicFile)))
    {
        bis.read(buffer, 0, buffer.length);

        clientManagerTemp.logger("Sending " + "src/Resources/Songs/" + names[2]+ ".mp3" + "(" + buffer.length + " bytes)");
        //write the file to the client

        toClient.write(buffer,0, buffer.length);
        toClient.flush();

        clientManagerTemp.logger("Finished sending");

    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

}

因此,如您所见,服务器发送文件很好,而我的客户端则收到它。它就是不能阻止won循环。谁能解释一下原因吗?这样我就能更好地理解流字节是如何在套接字上工作的。

**编辑当客户端收到文件时,即使在关闭客户端和服务器之后也可以播放它

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-04-23 13:07:20

您可以向客户端发送文件长度,客户端知道何时退出循环。

服务器

代码语言:javascript
运行
复制
private void findMusic(String input, ObjectOutputStream toClient)
{
    logoff();
    String[] names = input.split("[.]");
    clientManagerTemp.logger("Someone request song: " + names[2] + ".mp3");

    File musicFile = AudioUtil.getSoundFile("src/Resources/Songs/" + names[2]+ ".mp3");
    int fileLength = (int) musicFile.length();
    byte[] buffer = new byte[fileLength];

    try(BufferedInputStream bis = new BufferedInputStream(new FileInputStream(musicFile)))
    {
        bis.read(buffer, 0, buffer.length);

        clientManagerTemp.logger("Sending " + "src/Resources/Songs/" + names[2]+ ".mp3" + "(" + buffer.length + " bytes)");
        //write the file to the client

        toClient.writeInt(fileLength);
        toClient.write(buffer,0, buffer.length);
        toClient.flush();

        clientManagerTemp.logger("Finished sending");

    }
    catch (IOException e)
    {
        e.printStackTrace();
    }
}

客户端

代码语言:javascript
运行
复制
byte[] buffer = new byte[4096];
int current;
int fileLength = fromServer.readInt();

while ( fileLength > 0 && (current = fromServer.read(buffer, 0, Math.min(4096,fileLength))) > 0)
{
    bOS.write(buffer, 0 , current);
    fileLength -= current;
}
票数 3
EN

Stack Overflow用户

发布于 2018-04-23 13:01:46

这是由于读取方法的本质,在这里可以看到爪哇。此方法将被阻塞,直到有数据为止,所以循环永远不会结束。这是因为您从未关闭服务器端的流,只需刷新它,这会强制发送缓冲区中当前的所有数据,但不会关闭流。如果您从服务器端调用流上的.close(),那么应该退出客户端的while循环并继续播放代码。

我还没有对此进行测试,但从文档和代码的简要介绍来看,这似乎就是问题所在。

票数 2
EN

Stack Overflow用户

发布于 2018-04-23 13:03:49

如果您不关闭连接(服务器端),就不会有文件端/流端,除非您配置了读取超时,否则客户端将永远运行循环。

如果在发送完文件后不自动关闭循环,则首先将字节数(文件大小)发送给客户端,然后发送文件本身。这使得只读取客户端的确切字节数并在完成连接时关闭连接成为可能。另外,您可以发送一个特殊的序列,并在客户端检查它们以标记流的结束。

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

https://stackoverflow.com/questions/49981409

复制
相关文章

相似问题

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