首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android UDP Socket 通信:發送線程卡住?單 Socket 雙線程阻塞模式下無法同時收發

     編輯:程式設計綜合問答

問題現象

兩個線程:一個循環 socket.receive(packet) 阻塞接收,收到後啟動發送線程,發送時卡在 packet.getSocketAddress()。疑問:Socket 處於阻塞狀態時能否發送?

根因分析

Java/UDP 的 DatagramSocket 默認阻塞模式下,同一 Socket 不支持並發收發。 接收線程持續佔用 Socket 進行阻塞式 receive(),導致發送線程調用 send() 時同步等待,甚至死鎖。

解決方案

方案一:雙 Socket(推薦)

  • 創建兩個 DatagramSocket 綁定同一本地端口(需 setReuseAddress(true))。
  • 一個專職 receive(),一個專職 send(),互不干擾。

方案二:非阻塞模式 + Selector(NIO)

  • 使用 DatagramChannel 配置 configureBlocking(false)。
  • 註冊 SelectionKey.OP_READ | OP_WRITE 到 Selector。
  • 單線程事件循環處理收發,避免多線程同步複雜性。

方案三:單線程輪詢(簡單場景)

  • 設置 socket.setSoTimeout(100) 非無限阻塞。
  • 單線程循環:先 receive() 捕獲超時異常,再檢查發送隊列 send()。

代碼片段:雙 Socket 綁定同端口

DatagramSocket recvSocket = new DatagramSocket(null);
recvSocket.setReuseAddress(true);
recvSocket.bind(new InetSocketAddress(localPort));

DatagramSocket sendSocket = new DatagramSocket(null);
sendSocket.setReuseAddress(true);
sendSocket.bind(new InetSocketAddress(localPort)); // 同端口
// 此後 recvSocket 只收,sendSocket 只發

總結

UDP Socket 阻塞模式下單 Socket 不宜雙線程收發。**雙 Socket 綁定同端口**是最簡單有效的工程方案;高性能場景請上 NIO (DatagramChannel + Selector)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved