UDP包在Java中可以正常接收,但在Python中已损坏



我正试图从Android平板电脑录制音频并将其发送到python服务器。在字节包的开头,我包含了一些关于Android应用程序状态的相关信息(一个名为"活动"的字节数组——但考虑到它被Java服务器接收得很好,这应该无关紧要)。android代码如下:

                   int read = recorder.read(buffer, 0, buffer.length);
                    for (int a = 0; a < actives.length; a++) {
                        outBuffer[a+1] = (byte)actives[a];
                        logger = logger + Byte.toString(actives[a]) + ",";
                    }
                    int furthest=0;
                    for(int a =0; a < buffer.length; a++){
                        outBuffer[actives.length+1+a]=buffer[a];
                        if(buffer[a]!=0)furthest=a;
                    }
                    packet = new DatagramPacket(outBuffer, read,
                            serverAddress, PORT);
                    Log.d("writing", logger+Byte.toString(outBuffer[7])+".length"+Integer.toString(1+furthest+actives.length+1));
                    Log.d("streamer","Packet length "+outBuffer.length);
                    try {
                        socket.send(packet);
                    }catch (IOException e){
                        Log.e("streamer", "Exception: " + e);
                    }
                    Log.d("streamer","packetSent");

我使用Java服务器在另一端接收到一个干净的信号。接收到的java输出图像:!(https://i.stack.imgur.com/OCFmP.png)这是我的Java服务器:

DatagramSocket serverSocket = new DatagramSocket(3001);
int byteSize=970;
byte[] receiveData = new byte[byteSize];
DatagramPacket receivePacket = new DatagramPacket(receiveData,
        receiveData.length);
while(true){        // recieve data until timeout
                        try {
                            serverSocket.receive(receivePacket);
                            String rcvd = "rcvd from " + receivePacket.getAddress();
                           System.out.println("receiver"+"Received a packet!" +rcvd);
                            break;
                        }
                        catch (Exception e) {
                            // timeout exception.
                            System.out.println("Timeout reached without packet!!! " + e);
            timeoutReached=true;
                            break;
                        }
                 }
if(timeoutReached)continue;
    currTime = System.currentTimeMillis();
    data = receivePacket.getData();
下面是我的Python服务器的输出:! (https://i.stack.imgur.com/VXjLX.png)下面是代码:
import socket
ip="192.ip.address"
port=3001;
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM);
sock.bind(('',port));
while(True):
    data,addr=sock.recvfrom(970);
    print("address",addr);
    print("received a data!");
    print(data);

在python脚本的最后一行,我试图将"print(data)"更改为"print(data.decode())",在这种情况下,我得到这个错误:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xff in position 0: ordinal not in range(128)

我没有同时运行这些服务器我的猜测是,它必须做一些与Java使用unsigned int和python不这样做。在Python中是否有一种方法可以转换此数据,因为data.decode()不起作用?或者,我应该能够以某种方式在Java中转换数据?我尝试过的stackoverflow上的答案都没有起作用。

解码是正确的方法。在你的android应用程序明确提及字符编码。UTF-8是使用的标准字符集

你的日志很清楚。您正试图将数据包解码为ASCII(这是decode()函数的默认编码),但我猜它的ISO_8859_1或UTF-8(更有可能)。

下一步尝试data.decode('utf8', 'ignore')在你的android应用程序。注意:'ignore'是一个可选的参数,只在调试的情况下使用,因为它会忽略畸形(损坏)的数据,并尝试转换单个字符。如果您想在生产中使用decode(),请使用' strict'或不使用第二个参数('strict'是默认值)。

'utf8'的位置尝试其他选项从其他Python编码

这是相当残酷的正面攻击。我试着在Java中指定编码(在发送之前),就像另一个SO帖子建议的那样,但这没有帮助。因此,我通过将Android字节数组转换为逗号分隔的字符串,然后将字符串转换回UTF-8字节,从而避开了这个问题。

sendString="";
for(int a =0; a < buffer.length; a++){
           sendString=sendString+Byte.toString(buffer[a])+",";
}
byte[] outBuffer = sendString.getBytes("UTF-8");

确保每次执行while循环时都将字符串重置为null("),否则程序将变得非常慢。

然后在Python中,在接收到

之后:
data=data.decode("utf8");

虽然我对980个字符进行了字符串化,但它似乎并没有增加多少处理时间…虽然我确实希望我可以发送原始字节,因为速度对我来说非常重要。我不回答这个问题,也许有人能想出更好的解决办法。

相关内容

最新更新