当前位置: 首页 > 知识库问答 >
问题:

无法在不损坏文件和阻塞 while 循环的情况下保持套接字打开

翟黎明
2023-03-14

我有一个Java服务器和Android客户端。客户端通过TCP套接字向服务器发送3件事。第一个是int中的文件大小,第二个是一个长的序列号,第三个是它使用一个同时循环来发送一个pdf文件。

所有三个文件都成功地发送到服务器,但是要做到这一点,输出流(BufferedOutpuStream)必须在双方直接关闭,如果不这样做,那么发送到服务器的pdf文件将是不完整的和损坏的。

问题是,在客户端关闭输出流后,也关闭了套接字,我不能从服务器向客户端发送响应。我也不能在客户端打开一个新的输入流来接收这个响应。

有20个不同的Android客户端,所以需要相同的套接字来确保返回消息返回到它想要的正确客户端,因为服务器为每个连接的Android客户端启动一个单独的套接字对象。

如何保持插座打开?仍然能够发送完整的文件?

显示 while 循环的服务器代码示例

         @Override
        public void run() { // launch new thread

        fileSizeFromClient = dis.readInt();
        serialNumber = dis.readLong();

        byte[] buffer = new byte[fileSizeFromClient];

          while((count = dis.read(buffer)) > 0){
          bos.write(buffer, 0, count);
          }

         bos.close();

         } // end thread

显示while循环的客户端代码示例

             @Override
             public void run() { // launch new thread

             dos.writeInt((int)length); // sends the length as number bytes is file size
             dos.writeLong(serial); 

                int count = 0; // number of bytes

                while ((count = bis.read(bytes)) > 0) {
                    dos.write(bytes, 0, count);
                }
             dos.flush();
             dos.close();

             } // end thread

观察:

1 - 在 BufferedOutputStream 或 DataOuputStream 对象上调用 close() 将关闭套接字

2-如果outputStream.close()没有在客户端调用,那么在服务器代码中,它将被卡住或挂起,线程的执行将不会继续,将被阻塞,发送的pdf文件将不完整和损坏

3 - 如果未在服务器中调用 outputSteam.close(),则服务器代码不会像上面的 #2 那样被阻止或卡住,但发送的 pdf 文件将不完整或损坏

4 -如果在客户机和服务器中的while循环之后,直接在客户机和服务器的outputstreams上调用close(),那么客户机或服务器中的程序执行都不会出现阻塞或问题。并且pdf文件总是完好无损地到达。

编辑:我是否朝着完全错误的方向前进?发送 pdf 文件后关闭套接字并打开新套接字是否更好?如果那么如何使用早期套接字连接到的同一Android客户端打开。想要将响应消息发回相同的 Android 客户端,而不是其他客户端。

共有1个答案

崔涵亮
2023-03-14

由于在while循环之前您已经从客户端获得了文件大小,因此您可以修改服务器代码以仅读取文件大小的字节数,并在收到这些字节后关闭PDF流。

byte[] bufferPDF = new byte[fileSizeFromClient];
int count =0;
while (count!=fileSizeFromClient){
   bufferPDF[count]= disSocket.readByte();
   count++;
}
bosPDF.write(bufferPDF);
bosPDF.close();

/** Send response to client **/
dosSocket.write(responseBytes);

在客户端,你在发送文件后尝试从套接字读取,不需要关闭套接字。

while ((count = bisPDF.read(bytes)) > 0) {
  dosSocket.write(bytes, 0, count);
}
dosSocket.flush();

while(disSocket.read(responseBytes)>0){
   //Process the response from server
}
 类似资料:
  • 我有一个带感应帽的覆盆子皮。我制作了一个二进制时钟,我想在Sense hat的显示器上显示并保持更新。然而,我想要的能力,开关时钟与操纵杆中间。一切都很好,除了我的时钟的更新循环阻止任何新的输入一旦启动。 我一直在考虑如何解决这个问题。如何允许脚本/时钟保持运行,并且仍然接受来自操纵杆的新操作。但是一旦while循环开始,我就卡住了。我不知道该用谷歌搜索什么。我已经开始研究async/await,

  • 这周我刚刚开始学习C#并且正在尝试运行一个简单的代码,当用户输入文本时,它会提示用户输入一个数字,或者当用户输入一个负数时,它会提示用户输入一个正数(因此,对于文本是一个布尔运算,对于负数是一个if语句)。如果他们输入了一个有效的(正)数字,程序将继续进行其余的步骤。 然而,在此代码中,如果用户输入一个负数,然后输入一个文本,然后输入另一个负数,依此类推,似乎会中断循环并继续下一个操作。 代码是一

  • 问题内容: 为什么有人会喜欢阻止写而不是非阻止写?我的理解是,仅当您想确保写方法返回后,另一端获得了TCP数据包时,才希望阻止写操作,但是我什至不知道这是可能的。您将必须刷新,而刷新则必须刷新 底层操作系统的写套接字缓冲区 。那么,无阻塞套接字写是否有任何缺点?就性能而言,拥有较大的底层写套接字是否会缓冲一个不好的主意?我的理解是,底层套接字写缓冲区越小,当底层套接字缓冲区已满且isWritabl

  • 我们已经知道 Vert.x Api 是非阻塞,并且不会堵塞事件循环。 如果你堵塞事件循环,那事件循环将不能做别的事,因为它被阻塞了。如果所有的event loop被阻塞了,应用程序将完全停止! 所以不要这样做!你已经被警告。 阻塞的例子包括: Thread.sleep() 等待锁 等待互斥体或监视器 (例如同步段) 做一个长时间的数据库操作和等待返回 做复杂的计算,需要很长的时间。 死循环。 如果

  • 我有以下代码来下载通过TCP传输的文件: 一旦所有的字节都被处理了(它们总是被处理的,它像正常的一样工作,只是不退出循环),文件就被创建了,没有一个问题,但是,循环没有退出。

  • 问题内容: 我一直在努力在DigitalOcean上运行多个Puppeteer实例,但运气不好。我可以使用puppeteer- cluster之 类的工具同时运行〜5个,但是由于某种原因,整个过程几乎没有什么有用的消息。因此,我切换为在没有任何其他库的情况下生成〜5个子进程- 仅是Puppeteer本身。同样的问题。窒息而没有有用的错误。 我可以在本地很好地运行所有这些工作,但是在部署之后,我碰壁