当前位置:   article > 正文

Java实现UDP服务器在局域网中实现与客户端通信_java编写udp接口

java编写udp接口

  * UDP服务器
 * <p> UDP说明: 
 * <p>UDP是无连接的通信协议,本质上不分服务端和客户端,两个段都可以对方当作服务器。
 * <p> Java版本的可使用DatagramSocket接口实现,关键函数说明:
 * <p> .bind(): 表示监听,监听本机端口(任意定义),增加本地地址表明指明本地网卡;
 * <p> .send(): 表示发送数据,每个发送的数据包都要指明发送目的服务器地址和端口号;
 * <p> .receive(): 表示接收数据,每个接收数据包都要指明接收源服务器地址和端口号;
 * <>  笔记本开热点,就是新建独立网卡,组成局域网,局域网内设备可以相互通信,接收发送数据,发送方需要指明地址。
 * <p>使用方法:
 * <p>1.笔记嗯电脑开启局域网:
 * <p>本机开启WiFi热点,在cmd中ipconfig, 查看本机热点IP,如下:
 * <p>2. 查看本机局域网IP:
 * <p>无线局域网适配器 本地连接* 10:
 * <p>
 * <p>   连接特定的 DNS 后缀 . . . . . . . :
 * <p>   本地链接 IPv6 地址. . . . . . . . : fe80::e4xx:93xx:47xx:xxx%4
 * <p>   IPv4 地址 . . . . . . . . . . . . : 192.168.137.1   //这个就是热点局域网
 * <p>   子网掩码  . . . . . . . . . . . . : 255.255.255.0
 * <p>   默认网关. . . . . . . . . . . . . :
 * <p> 3. 手机连上局域网wifi热点,
 * <p> 在笔记本电脑上热点设备列表可以看到手机或者移动设备的名称和IP,也可以把其他机器当作服务器,对应IP就行。
 * <p> 4. 笔记本上运行server服务,监听本机地址端口(本地端口随意定义只要不重复就行):
 * <p>         // 设置自己的地址和端口号 用于相互通信,增加本地地址表明指明网卡(开热点就是新建独立网卡,组成局域网)
 * <p>         boundAddr = new InetSocketAddress("192.168.137.1", "9000");
 * <p>         log("bind: boundAddr=" + boundAddr);
 * <p>         sServerSocket.bind(boundAddr);
 * <p> 5. 客户端UDP程序把运行server服务的地址和端口当作远端服务器地址,运行就可以实现相互发数据了。

  1. package com.hulk.udp.test.server;
  2. import java.io.IOException;
  3. import java.net.DatagramPacket;
  4. import java.net.DatagramSocket;
  5. import java.net.InetSocketAddress;
  6. import java.net.SocketAddress;
  7. import com.hulk.util.HexUtils;
  8. import com.hulk.util.HulkTimeUtils;
  9. import com.hulk.util.TextUtils;
  10. import com.hulk.util.UdpDataUtils;
  11. /**
  12. * UDP服务器
  13. * <p> UDP说明:
  14. * <p>UDP是无连接的通信协议,本质上不分服务端和客户端,两个段都可以对方当作服务器。
  15. * <p> Java版本的可使用DatagramSocket接口实现,关键函数说明:
  16. * <p> .bind(): 表示监听,监听本机端口(任意定义),增加本地地址表明指明本地网卡;
  17. * <p> .send(): 表示发送数据,每个发送的数据包都要指明发送目的服务器地址和端口号;
  18. * <p> .receive(): 表示接收数据,每个接收数据包都要指明接收源服务器地址和端口号;
  19. * <> 笔记本开热点,就是新建独立网卡,组成局域网,局域网内设备可以相互通信,接收发送数据,发送方需要指明地址。
  20. * <p>使用方法:
  21. * <p>1.笔记嗯电脑开启局域网:
  22. * <p>本机开启WiFi热点,在cmd中ipconfig, 查看本机热点IP,如下:
  23. * <p>2. 查看本机局域网IP:
  24. * <p>无线局域网适配器 本地连接* 10:
  25. * <p>
  26. * <p> 连接特定的 DNS 后缀 . . . . . . . :
  27. * <p> 本地链接 IPv6 地址. . . . . . . . : fe80::e4xx:93xx:47xx:xxx%4
  28. * <p> IPv4 地址 . . . . . . . . . . . . : 192.168.137.1 //这个就是热点局域网
  29. * <p> 子网掩码 . . . . . . . . . . . . : 255.255.255.0
  30. * <p> 默认网关. . . . . . . . . . . . . :
  31. * <p> 3. 手机连上局域网wifi热点,
  32. * <p> 在笔记本电脑上热点设备列表可以看到手机或者移动设备的名称和IP,也可以把其他机器当作服务器,对应IP就行。
  33. * <p> 4. 笔记本上运行server服务,监听本机地址端口(本地端口随意定义只要不重复就行):
  34. * <p> // 设置自己的地址和端口号 用于相互通信,增加本地地址表明指明网卡(开热点就是新建独立网卡,组成局域网)
  35. * <p> boundAddr = new InetSocketAddress("192.168.137.1", "9000");
  36. * <p> log("bind: boundAddr=" + boundAddr);
  37. * <p> sServerSocket.bind(boundAddr);
  38. * <p> 5. 客户端UDP程序把运行server服务的地址和端口当作远端服务器地址,运行就可以实现相互发数据了。
  39. * <p>
  40. * @author hulk
  41. *
  42. */
  43. public class UdpServer {
  44. private static final String TAG = "UdpServer";
  45. private static final int LOCAL_UDP_BIND_PORT = UdpConstants.UDP_LISTEN_PORT;
  46. private static final String LOCAL_UDP_BIND_IP = UdpConstants.UDP_LISTEN_IP;
  47. private static final String STOP_MSG = UdpConstants.STOP_MSG;
  48. /**
  49. * UDP的socket
  50. */
  51. private DatagramSocket mServerSocket;
  52. /**
  53. * 本机绑定地址,通常为 InetSocketAddress 对象.
  54. */
  55. SocketAddress mBoundAddr = null;
  56. /**
  57. * 接收数据的最大buffer
  58. */
  59. int mUdpReceiveDataBufferSize = UdpConstants.UDP_RECEIVE_DATA_BUFFER_SIZE;
  60. boolean mStopped = false;
  61. public UdpServer() {
  62. //default
  63. }
  64. public UdpServer(InetSocketAddress boundAddr) {
  65. mBoundAddr = boundAddr;
  66. }
  67. public void setBoundAddr(InetSocketAddress boundAddr) {
  68. mBoundAddr = boundAddr;
  69. }
  70. public void setReceiveDataBufferSize(int udpReceiveDataBufferSize) {
  71. mUdpReceiveDataBufferSize = udpReceiveDataBufferSize;
  72. }
  73. /**
  74. * 连接的方法
  75. *
  76. * @param replyMsg 发送指令
  77. * @param iCallUdp 返回的接口数据
  78. */
  79. public void listen(String replyMsg, ICallUdp iCallUdp) {
  80. if (TextUtils.isEmpty(replyMsg)) {
  81. replyMsg = "$M";
  82. }
  83. log("listen: replyMsg=" + replyMsg);
  84. log("listen: udpReceiveDataBufferSize=" + mUdpReceiveDataBufferSize);
  85. iCallUdp.start();
  86. try {
  87. // 1. 创建服务端+端口
  88. if (mServerSocket != null) {
  89. log("Close last mServerSocket=" + mServerSocket);
  90. mServerSocket.close();
  91. mServerSocket = null;
  92. }
  93. mServerSocket = new DatagramSocket(null);
  94. mServerSocket.setReuseAddress(true);
  95. if(mBoundAddr == null) {
  96. // 设置自己的端口号 用于相互通信
  97. mBoundAddr = new InetSocketAddress(LOCAL_UDP_BIND_IP, LOCAL_UDP_BIND_PORT);
  98. log("listen: Created default boundAddr=" + mBoundAddr);
  99. }
  100. log("listen: bind boundAddr=" + mBoundAddr);
  101. mServerSocket.bind(mBoundAddr);
  102. //2.服务器准备接收数据
  103. while (!mStopped) {
  104. // 2.1 准备接收容器
  105. byte[] receiveContainer = new byte[mUdpReceiveDataBufferSize];
  106. // 封装成包
  107. DatagramPacket receivedPacket = new DatagramPacket(receiveContainer, receiveContainer.length);
  108. // 接收数据,使用 DatagramSocket的实例的 receive( DatagramPacket ) 方法进行接收
  109. log("listen: receive data waiting ...");
  110. mServerSocket.receive(receivedPacket);
  111. // 分析数据、打印数据
  112. byte[] receivedRawData = receivedPacket.getData();
  113. log("listen: receivedRawData.length=" + receivedRawData.length);
  114. byte[] receivedRealData = UdpDataUtils.trimData(receivedRawData);
  115. log("listen: receivedRealData.length=" + receivedRealData.length);
  116. String receivedRealDataHex = bytesToHex(receivedRealData);
  117. log("listen: receivedRealDataHex=" + receivedRealDataHex);
  118. try {
  119. //尝试用字符串去解析
  120. String recevedMsg = new String(receivedRealData);
  121. log("listen: received recevedMsg=" + recevedMsg);
  122. if(STOP_MSG.equals(recevedMsg)) {
  123. log("break from recevedMsg: " + recevedMsg);
  124. break;
  125. }
  126. } catch (Exception e) {
  127. loge("listen: string parsed failed: " + e);
  128. }
  129. // 2.2准备发送数据
  130. String timeStr = HulkTimeUtils.getCurrentTimeStr();
  131. String replyMsg2 = replyMsg + ", CurrentTime:" + timeStr;
  132. byte[] sendingData = replyMsg2.getBytes();
  133. // 2.3. 打包(发送的地点及端口)
  134. // IP 连接的目标IP地址
  135. // port 连接目标的 端口号
  136. SocketAddress destAddr = receivedPacket.getSocketAddress();
  137. log("listen: sending reply data=" + new String(sendingData));
  138. log("listen: sending reply data destAddr=" + destAddr);
  139. DatagramPacket packet = new DatagramPacket(sendingData, sendingData.length, destAddr);
  140. // 2.4 发送返回资源
  141. mServerSocket.send(packet);
  142. log("listen: sent reply sendingdata=" + bytesToHex(sendingData));
  143. // 回调传接收的数据
  144. iCallUdp.success(receivedRealData, replyMsg2);
  145. }
  146. log("listen: Finished.");
  147. } catch (Exception e) {
  148. loge("Error: " + e.toString(), e);
  149. iCallUdp.failure(e.getMessage());
  150. } finally {
  151. // 关闭资源
  152. closeSocket();
  153. }
  154. }
  155. /**
  156. * 关闭资源(对方在发送数据会出现异常)
  157. */
  158. public void closeSocket() {
  159. if(mServerSocket != null) {
  160. try {
  161. mServerSocket.close();
  162. } catch (Exception e) {
  163. //ignored
  164. }
  165. mServerSocket = null;
  166. }
  167. }
  168. /**
  169. * 将接收到byte数组转成String字符串
  170. *
  171. * @param bytes 接收的byte数组
  172. * @return string字符串
  173. */
  174. private static String bytesToHex(byte[] bytes) {
  175. return HexUtils.bytesToHex(bytes);
  176. }
  177. private static void log(String msg) {
  178. System.out.println(TAG + ": " + msg);
  179. }
  180. private static void loge(String msg) {
  181. loge(msg, null);
  182. }
  183. private static void loge(String msg, Throwable th) {
  184. System.err.println(TAG + ": " + msg);
  185. if(th != null) {
  186. th.printStackTrace();
  187. }
  188. }
  189. public void setStopped(boolean stopped) {
  190. mStopped = stopped;
  191. }
  192. public void stop() {
  193. mStopped = true;
  194. attemptSendStop();
  195. }
  196. /**
  197. * 通过给自己发送数据触发receive()等待函数
  198. */
  199. public void attemptSendStop() {
  200. if(mServerSocket != null) {
  201. byte[] data = STOP_MSG.getBytes();
  202. DatagramPacket packet = new DatagramPacket(data, data.length, mBoundAddr);
  203. try {
  204. // 发送返回资源
  205. mServerSocket.send(packet);
  206. } catch (IOException e) {
  207. loge("attemptStopServer failed: " + e, e);
  208. }
  209. }
  210. }
  211. }

完整代码下载链接: https://download.csdn.net/download/zhanghao_Hulk/87635930

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/146647?site
推荐阅读
相关标签
  

闽ICP备14008679号