我正在编写一个android源代码(但只是java)来与一些充当服务器的嵌入式设备进行通信。
我确信我的 UDP 数据报已到达设备,因为我可以观察到设备状态的变化。
但问题是我无法从服务器获得响应。没有收到任何内容,但我只是收到了我发送的内容的回声。我的来源如下。
public void sendSnapShot(View view) {
//send a udp datagram to the server.
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
try {
Log.e("Test", "send sendSnapShot onLine");
DatagramSocket clientSocket = new DatagramSocket();
byte[] sendData = new byte[1024];
String sentence = "$SNAPSHOT";
sendData = sentence.getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("192.168.5.255"), 9999);
clientSocket.send(sendPacket);
Log.e("Test", "Sent sendSnapShot REQUEST");
} catch (Exception e) {
Log.e("Test", "e", e);
}
return null;
}
}.execute();
}
上面的代码是向服务器传输数据报。在应用程序启动时,将启动以下线程来监听服务器发送的任何数据报。
private class ListenerThread implements Runnable {
//listen for incoming datagrams.
@Override
public void run() {
DatagramSocket serverSocket = null;
try {
InetAddress serverAddr = InetAddress.getByName("192.168.5.255");
serverSocket = new DatagramSocket(9999, serverAddr);
while (true) {
try {
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
receivePacket.getLength();
String receivedData = new String(receivePacket.getData(), 0, receivePacket.getLength());
if (!receivedData.startsWith("!HEARTBEAT")) {
Log.e("Test", "Received : " + receivedData);
} else {
Log.e("Test", "Received : HEARTBEAT");
}
} catch (Exception e) {
Log.e("Test", "FROM SERVER ", e);
}
}
} catch (Exception e) {
Log.e("Test", "Exception", e);
}
}
}
编写服务器代码的人(可能是用 C++ 编写的)说他在测试用例中得到了响应,那么我可能会缺少什么?上面的代码是否有可能忽略来自服务器的任何数据报并回显从我的代码发送的字节?
================================================== ===============================
我已经根据答案更改了我的代码。我不再使用监听线程了。这是我的代码。
public void sendBattery(View view) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
try {
Log.e("Test", "send Battery onLine");
DatagramSocket clientSocket = new DatagramSocket(9999, InetAddress.getByName("0.0.0.0"));
byte[] sendData = new byte[1024];
byte[] receivedata = new byte[1024];
String sentence = "$S0B255";
DatagramPacket receivePacket = new DatagramPacket(receivedata, receivedata.length);
sendData = sentence.getBytes();
String receivedData = " ";
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, InetAddress.getByName("192.168.5.1"), 9999);
clientSocket.send(sendPacket);
do{
clientSocket.receive(receivePacket);
receivedData = new String(receivePacket.getData(), 0, receivePacket.getLength());
Log.e("Test", receivedData + ", IP CHECK Sender: : " + receivePacket.getAddress().toString() + ", port : "+ receivePacket.getPort());
}while(true);
// Log.e("Test", "Sent BATTERY REQUEST COMPL");
} catch (Exception e) {
Log.e("Test", "e", e);
}
return null;
}
}.execute();
}
根据我接收到的心跳字节(将其转换为字符串将使其成为“!HEARTBEAT”),发送者是192.168.5.1。但我仍然只得到心跳字节。我会错过什么?
最佳答案
- 您正在接收自己的数据报,因为您正在广播(至 192.168.5.255)。您应该使用设备的实际 IP 地址。
- 您不应在每次发送时创建新的数据报套接字。 (您永远不会关闭该套接字,因此您也会泄漏套接字。)
- 您应该从接收数据的同一个套接字发送数据报。设备将(应该)回复请求来自的 IP:port,目前每次都不同,并且您将丢失绑定(bind)到该端口的发送套接字,并且发送 IP:port 不是 IP :你正在监听的端口,所以你听不到它。
- 您不应该将监听套接字绑定(bind)到特定的 IP 地址,当然也不应该绑定(bind)到广播地址。我很惊讶它能起作用。
关于Java UDP 套接字回显字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39907478/