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

Android - 客户端在接收回字符串之前关闭发送图像的连接

裴意
2023-03-14

我有一个Android应用程序,可以打开与服务器的套接字连接并将图像发送到 python 服务器。服务器接收该图像,并应发送回一个字符串以确认已收到图像。但是,在我结束输出流后套接字关闭,因此服务器接收图像,但客户端无法从服务器接收字符串,因为客户端关闭了连接。因此,我想做的是在套接字关闭之前返回一个字符串/文本,确认图像已到达用户客户端。

这是我的Python服务器,它在字节解码时接收图像并将其保存到一个目录,然后返回一条消息

from socket import *
import datetime
import cv2
import PIL.Image as Image
from PIL import ImageFile, Image
import io
import base64
import numpy as np
import pickle
import uuid


date_string = datetime.datetime.now().strftime("%Y-%m-%d-%H:%M")

port = 9999
s = socket(AF_INET, SOCK_STREAM)
s.bind(('', port))
s.listen(1)

while True:
    conn, addr = s.accept()
    img_dir = '/home/Desktop/frames_saved/'
    img_format = '.png'
    try:
        print("Connected by the ",addr)
        #date_string = datetime.datetime.now().strftime("%Y-%m-%d-%H:%M")
        filename = str(uuid.uuid4())
        with open(img_dir+filename+img_format, 'wb') as file:
            while True:
                data = conn.recv(1024*8)
                if data:
                    print(data)
                    try:
                        file.write(data)
                    except:
                        s = socket(AF_INET, SOCK_STREAM)
                        s.bind(('', port))
                        s.listen(1)
                        conn.sendall(("Hello World"))
                        

                    
                else:
                    print("no data")
    
                    break
    finally:
        conn.close() 

我正在尝试做的是在我的 android 客户端中接收编码字符串并打印/显示吐司。

Android客户端代码:

 public class SendImageClient extends AsyncTask<byte[], Void, Void> {


        @Override
        protected Void doInBackground(byte[]... voids) {
            isSocketOpen = true;
            try {
                Socket socket = new Socket("192.168.0.14",9999);
                OutputStream out=socket.getOutputStream();
                DataOutputStream dataOutputStream = new DataOutputStream(out);
                BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                StringBuilder response = new StringBuilder();
                String line;

                while (isSocketOpen){
                    Log.d("IMAGETRACK", "Wrote to the socket[1]");
                    dataOutputStream.write(voids[0],0,voids[0].length);
                    while ((line = input.readLine()) != null)
                        Log.d("IMAGETRACK3", "Wrote to the socket[3]");
                    response.append(line);
                    Message clientmessage = Message.obtain();
                    clientmessage.obj = response.toString();
                    Log.d("[MESSAGE]", String.valueOf(clientmessage));
                    // Tries to receive a message from the server
                    out.close();
                    input.close();
                    if(isSocketOpen == false){
                        Log.d("CLOSED", "CLOSED CONNECTION");
                        socket.close();

                        break;
                    }
                }
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }


            return null;
        }
    }

此外,我注意到执行out.close(;也会关闭流套接字。以下是服务器发送和接收映像后的日志:

D/IMAGETRACK: Wrote to the socket[1]
D/IMAGETRACK: Wrote to the socket[1]
W/System.err: java.net.SocketException: Socket closed
W/System.err:     at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:124)
        at java.net.SocketOutputStream.write(SocketOutputStream.java:161)
        at java.io.DataOutputStream.write(DataOutputStream.java:107)
        at MyApp.MainActivity$SendImageClient.doInBackground(MainActivity.java:2792)
        at MyApp.MainActivity$SendImageClient.doInBackground(MainActivity.java:2780)
        at android.os.AsyncTask$3.call(AsyncTask.java:394)
W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:305)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:923)

如果我尝试移动out.close();在同时循环之后,客户端将向服务器发送无限量的数据,当我关闭服务器以结束接收的无限数据时,我将有一个10MB或更多的图像,而不是70Kb的图像,这取决于我接收字节的日志方式。

从表面上看,我认为我需要以某种方式停止发送图像,而不关闭服务器来监听发送回来的图像。我怎样才能在不关闭套接字的情况下做到这一点?

共有1个答案

房新翰
2023-03-14

套接字关闭的原因很简单。我以前有这样的示例程序。你有两种选择。您用于发送和接收文件的体系结构不完整且不正确。

一种选择是,您可以自己定义一个发送和接收的协议,这不是标准的。例如,您可以定义特殊字符,如##内飞##,并在您的图像之后发送,然后不要关闭套接字。服务器理解图像被接收,仅此而已。然后在客户端调用接收方法直到套接字结束,但之前,您必须发送数据字符串返回以确认图像已收到,客户端在收到此字符串时关闭套接字。记住明智地添加套接字超时,以防止无限套接字等待。

第二种解决方案是,您可以使用标准协议,如< code>HTTP或< code>FTP,但必须读取这些协议的标准,如标头和正文值,并且还必须以< code>multipart的形式发送和接收文件。

 类似资料:
  • socket.io 0.9 node.js 0.10.15 速递3.3.4 即:调用 --服务器端 --客户端

  • 问题内容: 如何关闭客户端的套接字连接? 我在用: socket.io 0.9 node.js 0.10.15 express3.3.4 即:呼叫 -服务器端 - 客户端 如果加载测试页,则需要来自服务器的一些值(getInitData)。 在第一页上,我获取一次数据,在重新加载或第二遍上,我获取两次数据,依此类推。 重新加载页面以及离开页面后,服务器端的连接将自动关闭。 但是在客户端,连接仍然打

  • 我刚刚开始使用hazelcast[3.3.1]。根据hazelcast应用程序和客户端教程,我创建了一个hazelcast应用程序实例和一个客户端(使用eclipse IDE)。 从客户端,我能够将对象添加到地图并成功获取它们。但是,我在实例的控制台上看到以下警告,它们似乎警告客户端断开连接。这是每个客户端get/put的正常行为吗? 在退出客户端程序之前,是否有适当的方法断开客户端与实例的连接?

  • 我遇到了一个有趣的问题,HTTP 1.1 POST请求的TCP连接在请求之后立即关闭(即,在服务器可以发送响应之前)。 关于测试环境的一些细节: 客户端-Windows XP、Internet Explorer 8、Flash player 12。 服务器-Java 7 在上述行为之前,我们有几个长期存在的TCP连接,每个都被重用用于多个HTTP请求;我们打开一个长轮询,当这个轮询完成时,打开另一

  • 问题内容: 我应该在哪里关闭与Elasticsearch客户端的连接?我正在使用Spring,并且我不想使用Elasticsearch集成,因为我想学习如何首先完成它。应该只为该应用程序创建一个客户端吗?意味着它将具有单例范围?还是应该具有原型范围并为每次交互关闭连接? 问题答案: 您应该为每个应用程序使用一个客户端,使其成为单例并在应用程序关闭时关闭。

  • 我正在开发一个基于Firebase的聊天演示应用程序的Android应用程序。我面临的问题是,当我想传输图像时,我不知道如何处理这种情况。发送图像时,我在Base64中编码,并将其作为字符串发送。那么这里对图像的解码过程又会是怎样的呢?