Android UDP不接收数据

Posted

技术标签:

【中文标题】Android UDP不接收数据【英文标题】:Android UDP not receiving data 【发布时间】:2021-02-25 13:08:08 【问题描述】:

我在 android 中有一个 DatagramSocket 的实现,它试图从设置为服务器的 STA 设备接收数据。我有两个端口,一个是命令端口,第二个是数据流。命令端口在 TCP 协议上运行并且工作正常,而 UDP 端口由于某种原因没有接收到数据。我可以向 TCP 端口发送开始传输命令,并且 UDP 端口开始输出数据,从运行模拟器的计算机上观察到,但数据报套接字没有接收到数据。我已经在物理设备上尝试过,但仍然没有运气。我也知道这是可行的,因为我有一个 UDP 的 python 实现,运行在同一台设备上运行良好。

我的实现概览:

TCP 和 UDP 在不同的不同线程上运行(使用协程)。

我使用的权限包括:

uses-permission android:name = "android.permission.INTERNET"
uses-permission android:name = "android.permission.ACCESS_NETWORK_STATE"

最大 UDP 数据包大小 200 字节

Android 代码片段(不工作)

private val hostIP: String = "10.0.0.1"
private val commandPort: Int = 6660
private val streamPort: Int = 6670


private fun sendTcpCommand(command: Int = 2) 

  GlobalScope.launch 
      try 
          val socketCommand = Socket(inetAddress, commandPort)

          if (socketCommand.isConnected) 
              val clientCommandOutput = DataOutputStream(socketCommand.getOutputStream())

              val oByteArray = byteArrayOf(command.toByte())

              clientCommandOutput.write(oByteArray)

           else 
              Log.d(
                  TAG,
                  "createIOConnections: socket is not connect?: $socketCommand.isClosed"
              )
          
          val inputStream = DataInputStream(socketCommand.getInputStream())
          val response = inputStream.readBytes()
          val responseMap = responseInterpreter(response, command)
          socketCommand.close()

       catch (e: Exception) 
          e.printStackTrace()
      
  

  private fun openUdpPort() 
      GlobalScope.launch 
          try 
              val datagramSocketStream: DatagramSocket? = DatagramSocket(null)
              datagramSocketStream?.reuseAddress = true
              datagramSocketStream?.broadcast = true
              datagramSocketStream?.bind(InetSocketAddress(streamPort))

              val bufferLen = 200
              val bufferByteArray = ByteArray(bufferLen)
              val datagramPacket = DatagramPacket(bufferByteArray, bufferByteArray.size)

              datagramSocketStream?.receive(datagramPacket)

              val noBytesRead = datagramPacket.length
              interpretUdpData(datagramPacket.data)

           catch (e: Exception) 
              e.printStackTrace()
          
      
  

Python 代码片段(在计算机上运行)

CONTROL_SERVER_IP = "10.0.0.1"
STREAM_SERVER_IP = "10.0.0.100"

if self.socket == self.CONTROL_SOCK:
      try:
          self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      except socket.error as e:
          print("Failed to create socket.")
          print(f'Error: e')
          sys.exit()
      print("Socket Created.")



      # Connect the socket to the port where the server is listening
      server_address = (self.server_ip, self.socket)
      print(sys.stderr, 'connecting to %s port %s' % server_address)
      self.sock.settimeout(5)
      try:
          self.sock.connect(server_address)
          print("Port is open")
      except socket.timeout as e:
          print(
              "Server connection failed. Please check that the server is on and that the server and client are connected.")
          print(f'Error: e')
          sys.exit()
  else:
      try:
          self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
      except socket.error as e:
          print("Failed to create socket.")
          print(f'Error: e')
          sys.exit()
      print("Socket Created.")



      # Connect the socket to the port where the server is listening
      server_address = (self.server_ip, self.socket)
      print(sys.stderr, 'connecting to %s port %s' % server_address)
      self.sock.settimeout(5)
      try:
          self.sock.bind(server_address)
          print("Port is open")
      except socket.timeout as e:
          print(
              "Server connection failed. Please check that the server is on and that the server and client are connected.")
          print(f'Error: e')
          sys.exit()
  return self.sock


      print("Reading Meaurements.")
      self.thread_running = True
      measurements = Measurements()
      full_chunk = b''
      new_packet = True
      pointer = 0
      while self.thread_running:
          try:
              msg, address = sock.recvfrom(200)
              # msg = sock.recv(16)  # 16 byte buffer
          except socket.error as e:
              print(f'Error: e')
              break
              self.disconnect()
              self.terminate_thread()
              sys.exit()

在 android UDP 套接字上尝试使用地址 0.0.0.0 和 10.0.0.100。

任何关于为什么这不适用于 Android 的指针都会很棒!

【问题讨论】:

【参考方案1】:

您没有在设备上设置接收端口

val datagramSocketStream: DatagramSocket? = DatagramSocket(PORT)

这本身不是问题,但这意味着您依赖于接收广播消息。你可能有两个问题让你绊倒。模拟器可能正在更改您的预期 IP,或者您的手机可能不接受广播消息。 见此链接:Datagram (UDP) receiver not working - not receiving broadcast packets

【讨论】:

感谢您的延误。此后代码已更新,实际上我在服务器端遇到了问题,但当时可能一直在调整数据报套接字输入(疯狂地更改变量)。最后是:private val datagramSocketStream = DatagramSocket(Constants.STREAM_PORT) 所以会为你投票。

以上是关于Android UDP不接收数据的主要内容,如果未能解决你的问题,请参考以下文章

android-Android udp接收不到组播,请问如何解决

Android UDP 通信。无法从设备接收数据

统一时C#脚本上的UDP服务器启动但无法接收数据包

Android对UDP组播接收数据的有限支持

android中netty使用udp连接能发送数据,

Unity 游戏内无法接收 UDP 数据包