Java-клиент не отправляет сообщение целиком на сервер Python? - PullRequest
0 голосов
/ 30 января 2019

Я пишу программу в Android Studio, которая общается с сервером Python.Я пытался отправить длинное сообщение (mp3-файл, закодированный в base64 - около 10 Кбайт).Проблема в том, что когда я проверяю то, что я получил на сервере, я получаю намного меньше 10 Кбайт.

Кто-нибудь знает, как это исправить?

Заранее спасибо.

Запись сообщения и помещение его в 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))

РЕДАКТИРОВАТЬ: размер сообщениязначение верное (14806 - размер сообщения, которое должно быть получено в следующей строке), но оно все еще не получает его.

РЕДАКТИРОВАТЬ2: Я понял, плохо выложите решение в ответах

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Так что проблема не в длине файла или чем-то еще.Проблема заключалась в том, что функция recv в python получала некоторые байты, но код продолжал работать по какой-то причине, поэтому он не получил всего сообщения.

Решение состоит в том, чтобы добавить функцию, которая не продолжается до тех пор, пока не будет получена вся указанная длина.Я нашел решение в следующем посте: Python Socket получает большой объем данных

Я также добавлю код:

Заменим функцию recv на recvall (розетка, размер).Это не мой код, он был опубликован Адамом Розенфилдом и отредактирован Хедде ван дер Хайде.

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
0 голосов
/ 30 января 2019

Ваш 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").

Примечание: для замены кода «send the length» см. Преобразование целого числа в байтовый массив (Java)

...