UDP数据包在Java中收到,但在Python中已损坏(UDP Packet received okay in Java but corrupted in Python)

我正在尝试从Android平板电脑录制音频并将其发送到python服务器。 在字节数据包的开头,我包含了一些关于Android应用程序状态的相关信息(一个名为“actives”的字节数组 - 但考虑到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输出图片:!( http://i.imgur.com/31UWzya.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服务器的输出:!( http://i.imgur.com/RYkcCCE.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执行某些操作而python没有这样做。 在Python中有没有办法可以转换这些数据,因为data.decode()不起作用? 或者,我应该能够以某种方式转换Java中的数据? 我尝试过的stackoverflow上的答案都没有奏效。

I am trying to record audio from an Android tablet and send it to a python server. At the start of the byte packet, I include some relevant information about the state of the Android app (A byte array called "actives" -- but considering it's receiving fine by a Java server, this should not be relevant). The android code is as follows:

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");

I receive a clean signal on the other end using a Java server. Image of received java output: !(http://i.imgur.com/31UWzya.png) This is my Java server:

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();

Here is my Python server's output: !(http://i.imgur.com/RYkcCCE.png) And here is the code:

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);

In the last line of the python script, I have tried to change "print(data)" to "print(data.decode())", in which case I get this error:

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

I am not running these servers at the same time My guess is that it has to do something with Java using unsigned ints and python not doing that. Is there a way in Python that I can convert this data, because data.decode() is not working? Alternatively I should be able to convert the data in Java somehow? None of the answers on stackoverflow that I have tried have worked.

最满意答案

解码是正确的方法。 在你的Android应用程序中明确提到字符编码。 UTF-8是使用的标准Charset。

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

接下来在你的Android应用程序中尝试data.decode('utf8', 'ignore') 。 注意: 'ignore'是一个可选参数,仅在调试时使用,因为它会忽略格式错误(损坏)的数据并尝试转换单个字符。 如果要在生产中使用decode(),请使用' strict'或不使用第二个参数( 'strict'是默认值)。

代替'utf8'尝试其他Python编码的其他选项。

This was pretty brutal to attack head-on. I tried specifying the encoding in Java (before sending) like another SO post suggested, but that didn't help. So I side-stepped the problem by converting my Android byte array into a comma-separated string, then converting the string back into UTF-8 bytes.

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

Make sure you reset your string to null ("") each time you go through the while loop, or your ish will get very slow af.

Then in Python,right after receiving:

data=data.decode("utf8");

Although I am stringifying 980 characters, it does not appear to add much to the processing time... although I do wish that I could send the raw bytes, as speed is very important to me here. I'll leave the question open in case someone can come up with a better solution.

UDP数据包在Java中收到,但在Python中已损坏(UDP Packet received okay in Java but corrupted in Python)

我正在尝试从Android平板电脑录制音频并将其发送到python服务器。 在字节数据包的开头,我包含了一些关于Android应用程序状态的相关信息(一个名为“actives”的字节数组 - 但考虑到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输出图片:!( http://i.imgur.com/31UWzya.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服务器的输出:!( http://i.imgur.com/RYkcCCE.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执行某些操作而python没有这样做。 在Python中有没有办法可以转换这些数据,因为data.decode()不起作用? 或者,我应该能够以某种方式转换Java中的数据? 我尝试过的stackoverflow上的答案都没有奏效。

I am trying to record audio from an Android tablet and send it to a python server. At the start of the byte packet, I include some relevant information about the state of the Android app (A byte array called "actives" -- but considering it's receiving fine by a Java server, this should not be relevant). The android code is as follows:

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");

I receive a clean signal on the other end using a Java server. Image of received java output: !(http://i.imgur.com/31UWzya.png) This is my Java server:

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();

Here is my Python server's output: !(http://i.imgur.com/RYkcCCE.png) And here is the code:

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);

In the last line of the python script, I have tried to change "print(data)" to "print(data.decode())", in which case I get this error:

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

I am not running these servers at the same time My guess is that it has to do something with Java using unsigned ints and python not doing that. Is there a way in Python that I can convert this data, because data.decode() is not working? Alternatively I should be able to convert the data in Java somehow? None of the answers on stackoverflow that I have tried have worked.

最满意答案

解码是正确的方法。 在你的Android应用程序中明确提到字符编码。 UTF-8是使用的标准Charset。

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

接下来在你的Android应用程序中尝试data.decode('utf8', 'ignore') 。 注意: 'ignore'是一个可选参数,仅在调试时使用,因为它会忽略格式错误(损坏)的数据并尝试转换单个字符。 如果要在生产中使用decode(),请使用' strict'或不使用第二个参数( 'strict'是默认值)。

代替'utf8'尝试其他Python编码的其他选项。

This was pretty brutal to attack head-on. I tried specifying the encoding in Java (before sending) like another SO post suggested, but that didn't help. So I side-stepped the problem by converting my Android byte array into a comma-separated string, then converting the string back into UTF-8 bytes.

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

Make sure you reset your string to null ("") each time you go through the while loop, or your ish will get very slow af.

Then in Python,right after receiving:

data=data.decode("utf8");

Although I am stringifying 980 characters, it does not appear to add much to the processing time... although I do wish that I could send the raw bytes, as speed is very important to me here. I'll leave the question open in case someone can come up with a better solution.