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 中的数据? None 我试过的关于 Whosebug 的答案都有效。
解码是正确的方法。在您的 android 应用中明确提及字符编码。 UTF-8 是使用的标准字符集。
你的日志很清楚。您正在尝试将数据包解码为 ASCII(这是 decode() function 的默认编码),但我猜它是 ISO_8859_1 或 UTF-8(更有可能)。
接下来在您的 android 应用中尝试 data.decode('utf8', 'ignore')
。注意:'ignore'
是一个可选参数,仅在调试时使用,因为它会忽略格式错误(损坏)的数据并尝试转换单个字符。如果你想在生产中使用 decode() 使用 'strict'
或没有第二个参数('strict'
是默认值)。
代替 'utf8'
尝试其他 Python Encodings 的其他选项。
这正面攻击是相当残酷的。我尝试像另一个 SO post 建议的那样在 Java 中指定编码(在发送之前),但这没有帮助。因此,我通过将 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 (""),否则您的 ish 会变得很慢。
然后在 Python,收到后立即:
data=data.decode("utf8");
虽然我正在对 980 个字符进行字符串化处理,但它似乎并没有增加太多处理时间...虽然我确实希望我可以发送原始字节,因为在这里速度对我来说非常重要。如果有人能想出更好的解决方案,我会留下这个问题。
我正在尝试从 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 中的数据? None 我试过的关于 Whosebug 的答案都有效。
解码是正确的方法。在您的 android 应用中明确提及字符编码。 UTF-8 是使用的标准字符集。
你的日志很清楚。您正在尝试将数据包解码为 ASCII(这是 decode() function 的默认编码),但我猜它是 ISO_8859_1 或 UTF-8(更有可能)。
接下来在您的 android 应用中尝试 data.decode('utf8', 'ignore')
。注意:'ignore'
是一个可选参数,仅在调试时使用,因为它会忽略格式错误(损坏)的数据并尝试转换单个字符。如果你想在生产中使用 decode() 使用 'strict'
或没有第二个参数('strict'
是默认值)。
代替 'utf8'
尝试其他 Python Encodings 的其他选项。
这正面攻击是相当残酷的。我尝试像另一个 SO post 建议的那样在 Java 中指定编码(在发送之前),但这没有帮助。因此,我通过将 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 (""),否则您的 ish 会变得很慢。
然后在 Python,收到后立即:
data=data.decode("utf8");
虽然我正在对 980 个字符进行字符串化处理,但它似乎并没有增加太多处理时间...虽然我确实希望我可以发送原始字节,因为在这里速度对我来说非常重要。如果有人能想出更好的解决方案,我会留下这个问题。