Java客户端不会将整个消息发送到python服务器吗?

时间:2019-01-30 11:34:14

标签: java android python python-2.7 sockets

我正在android studio中编写一个与python服务器通信的程序。我试图发送一条长消息(以base64编码的mp3文件-大约10k字节)。问题是,当我检查服务器中收到的内容时,得到的字节数少于10k。

有人知道如何解决吗?

谢谢。

记录消息并将其放入base64:

// Record audio from user in mp3 format
                    MediaRecorder recorder = new MediaRecorder();
                    recorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                    recorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                    recorder.setOutputFile(Environment.getExternalStorageDirectory()
                                           .getAbsolutePath() + "/messageRecord.mp3");
                    recorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
                    recorder.prepare();
                    recorder.start();

                    TimeUnit.SECONDS.sleep(5);
                    recorder.stop();

                    File file = new File(Environment.getExternalStorageDirectory()
                                         .getAbsolutePath() + "/messageRecord.mp3");
                    int size = (int) file.length();
                    byte[] bytes = new byte[size];
                    BufferedInputStream buf = new BufferedInputStream(new FileInputStream(file));
                    buf.read(bytes, 0, bytes.length);
                    buf.close();
                    String content = Base64.encodeToString(bytes, Base64.DEFAULT);

                    // Prepare audio message request
                    JSONObject sendRecordReq = new JSONObject();
                    sendRecordReq.put("code", Codes.SPEECH_TO_TEXT_CODE);
                    sendRecordReq.put("src_phone", ChatScreen.this.srcPhone);
                    sendRecordReq.put("dst_phone", ChatScreen.this.dstPhone);
                    sendRecordReq.put("content", content);

                    // Send message request
                    ChatScreen.this.client.send(sendRecordReq);

我如何发送:

//In class client
    public void send(JSONObject request) {
        this.outgoingMessages.addConversationFlow(request); //Send request
    }
//In class OutgoingMessages
    public void run() {
        try {
            while (true) {
                while(!this.conversationFlow.isEmpty()) {
                    JSONObject msgToSend = this.conversationFlow.remove();
                    String strRequest = msgToSend.toString();
                    this.out.write(Integer.toString(strRequest.length()).getBytes()); //Sends message size
                    this.out.write(strRequest.getBytes()); //Sends message
                }
            }
        }
        catch (Exception e) {
            System.out.println(e);
        }
    }

服务器:

while True:
            # Receiving data size from client
            message_size = int(client_socket.recv(MAX_SIZE_LEN))

            # Receiving data from the client
            client_message = client_socket.recv(message_size)
            print client_message
            # Add message to messages queue with client's socket
            MESSAGES_QUEUE.append((client_socket, client_message))

编辑: “ message_size”值是正确的(14806-在下一行中应接收的消息大小),但仍不能全部接收。

EDIT2: 我想通了,把解决方案贴在答案中

2 个答案:

答案 0 :(得分:0)

您的Java代码正在以无法正常工作的协议发送数据。

如果输入的JSON对象是字符串'a',则将其发送:

3"a"

如4个字节:51、34、97、34。

“这是数据多长时间”部分结束时,python端不知道。

我假设您打算发送的内容类似于:

00, 00, 00, 03, 34, 97, 34.

换句话说:4个字节,包含一个网络字节序,先发送带有长度的整数值,然后再发送那么多字节。

另外,请勿致电.getBytes();将字符串转换为字节时,应始终明确指定编码。根据定义,JSON或多或少都是UTF-8,因此,请改为调用.getBytes("UTF-8")

注意:要替换您的“发送长度”代码,请参见Convert integer into byte array (Java)

答案 1 :(得分:0)

所以问题不在于文件的长度或其他任何东西。问题在于,python中的recv函数将获取一些字节,但是由于某些原因,代码仍在继续,因此未获得完整的消息。

解决方案是添加一个函数,直到收到指定的整个长度,该函数才继续。我在下一篇文章中找到了解决方案: Python Socket Receive Large Amount of Data

我还将添加代码:

用recvall(socket,size)替换recv函数。这不是我的代码,由亚当·罗森菲尔德(Adam Rosenfield)发布,由海德·范·德·海德(Hedde van der Heide)编辑。

def recvall(sock, n):
    # Helper function to recv n bytes or return None if EOF is hit
    data = b''
    while len(data) < n:
        packet = sock.recv(n - len(data))
        if not packet:
            return None
        data += packet
    return data