当前位置:   article > 正文

Android——Tcp服务端实现_android tcp servers

android tcp servers

Android——Tcp服务端
        传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
        Tcp分为服务端(网络应用程序)和客户端(网络应用程序),Tcp通信过程,首先打开服务器监听自己的网络通信端口(假设为7628),打开客户端,设置好要连接的ip地址和服务器的网络通信端口(7628),这样服务器监听到网络通信端口有连接,二者就建立了连接。
客户端:可以连接服务端、发送数据、接收数据、关闭连接等。
服务端:可以实现绑定通信端口,接收客户端连接、接收数据、发送数据等。

在java项目中我们可以较为快捷地使用TCP通讯,但想要在Android中使用还有很多要注意的地方。下面我们来学习下Tcp服务端在Android上的实现。

我之前做过一个项目里有个要通过Tcp获取智能手环上电量、心率,血压血氧、步数等基本数据的功能。(这里只是个功能一样的简单小Demo,报文需要处理才能看到想要的信息)

服务端ServerSocket的构造方法:
1、ServerSocket():构造一个新的未绑定的ServerSocket。
2、ServerSocket(int port):构造一个新的ServerSocket并绑定到指定端口,如果port等于0,则端口由系统自动分配。
3、ServerSocket(int port,int backlog):构造一个新的ServerSocket并绑定到指定端口以及指定进入队列的数目。如果port等于0,则端口由系统自动分配。
4、ServerSocket(int port,int backlog,InetAddress localAddress):构造一个新的ServerSocket并绑定到指定端口以及指定进入队列的数目。如果port等于0,则端口由系统自动分配。如果localAddress为null,则可以使用任意地址。


Tcp服务端使用步骤为:

①创建ServerSocket,绑定指定端口

  1. try {
  2. //开启服务、指定端口号
  3. socket = new ServerSocket(mServerPort);
  4. } catch (IOException e) {
  5. e.printStackTrace();
  6. Toast.makeText(this, "服务开启失败", Toast.LENGTH_SHORT).show();
  7. return;
  8. }

②调用ServerSocket的accept(),监听连接请求

③调用Socket类中的getInputStream()和getOutputStream()获取输入输出流

  1. class SocketAcceptThread extends Thread {
  2. @Override
  3. public void run() {
  4. try {
  5. //等待客户端的连接,Accept会阻塞,直到建立连接,
  6. //所以需要放在子线程中运行。
  7. mSocket = socket.accept();
  8. //获取输入流
  9. mInStream = mSocket.getInputStream();
  10. //获取输出流
  11. mOutStream = mSocket.getOutputStream();
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. startAccept();
  15. return;
  16. }
  17. Log.i(TAG, "accept success");
  18. SocketReceive();
  19. }
  20. }

 

​​​​​​​ ④接收、发送数据

  1. /**
  2. * 发送
  3. */
  4. private void sendText() {
  5. if (mSocket == null) {
  6. Toast.makeText(MainActivity.this, "没有客户端连接", Toast.LENGTH_LONG).show();
  7. return;
  8. }
  9. String str = content.getText().toString();
  10. if (str.length() == 0) {
  11. return;
  12. }
  13. Message msg = new Message();
  14. msg.what = Two;
  15. msg.obj = str;
  16. mSubThreadHandler.sendMessage(msg);
  17. }
  18. private void writeMsg(String msg) {
  19. if (msg.length() == 0 || mOutStream == null) {
  20. return;
  21. }
  22. try {
  23. //发送
  24. mOutStream.write(msg.getBytes());
  25. mOutStream.flush();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
int count = mInStream.read(buffer);

 ⑤关闭服务

  1. if (socket != null) {
  2. try {
  3. socket.close();
  4. } catch (IOException e) {
  5. e.printStackTrace();
  6. }
  7. }

注意: 在清单文件中添加权限

<uses-permission android:name="android.permission.INTERNET"/>

下面是MainActivity.java完整代码 :

  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  2. /**
  3. * 设置
  4. */
  5. private Button setting;
  6. /**
  7. * 开启服务
  8. */
  9. private Button open_service;
  10. /**
  11. * 输入内容
  12. */
  13. private EditText content;
  14. /**
  15. * 发送
  16. */
  17. private Button send_out;
  18. /**
  19. * 接收到的数据
  20. */
  21. private EditText receive;
  22. private final String TAG = "MainActivity";
  23. private static final char HexCharArr[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
  24. /**
  25. * 服务端端口
  26. */
  27. private int mServerPort;
  28. private SharedPreferences sp;
  29. private static final String PORT = "port";
  30. public Socket mSocket;
  31. private HandlerThread mHandlerThread;
  32. /**
  33. * 子线程中的Handler实例
  34. */
  35. private Handler mSubThreadHandler;
  36. private SocketAcceptThread mAcceptThread;
  37. private SocketReceiveThread mReceiveThread;
  38. private ServerSocket socket;
  39. /**
  40. * 输出流
  41. */
  42. private OutputStream mOutStream;
  43. /**
  44. * 输入流
  45. */
  46. private InputStream mInStream;
  47. private static final int One = 1;
  48. private static final int Two = 2;
  49. private Handler mHandler = new Handler() {
  50. @Override
  51. public void handleMessage(@NonNull Message msg) {
  52. switch (msg.what) {
  53. case One:
  54. String sb = receive.getText().toString() + "\r\n" + (String) msg.obj;
  55. receive.setText(sb);
  56. break;
  57. default:
  58. break;
  59. }
  60. }
  61. };
  62. @Override
  63. protected void onCreate(Bundle savedInstanceState) {
  64. super.onCreate(savedInstanceState);
  65. setContentView(R.layout.activity_main);
  66. setting = findViewById(R.id.setting);
  67. open_service = findViewById(R.id.open_service);
  68. content = findViewById(R.id.content);
  69. send_out = findViewById(R.id.send_out);
  70. receive = findViewById(R.id.receive);
  71. setting.setOnClickListener(this);
  72. open_service.setOnClickListener(this);
  73. send_out.setOnClickListener(this);
  74. //获取sharedPreferences对象
  75. sp = getSharedPreferences("settings", Context.MODE_PRIVATE);
  76. //如果key不存在,则返回默认defValue
  77. mServerPort = sp.getInt(PORT, 7628);
  78. initHandlerThraed();
  79. }
  80. @Override
  81. protected void onDestroy() {
  82. super.onDestroy();
  83. Log.i(TAG, "onDestory");
  84. closeConnect();
  85. if (socket != null) {
  86. try {
  87. socket.close();
  88. } catch (IOException e) {
  89. e.printStackTrace();
  90. }
  91. }
  92. }
  93. private void closeConnect() {
  94. try {
  95. if (mOutStream != null) {
  96. mOutStream.close();
  97. }
  98. if (mInStream != null) {
  99. mInStream.close();
  100. }
  101. if (mSocket != null) {
  102. mSocket.close(); //关闭socket
  103. mSocket = null;
  104. }
  105. } catch (IOException e) {
  106. e.printStackTrace();
  107. }
  108. if (mReceiveThread != null) {
  109. mReceiveThread.threadExit();
  110. mReceiveThread = null;
  111. }
  112. }
  113. @Override
  114. public void onClick(View v) {
  115. switch (v.getId()) {
  116. //设置
  117. case R.id.setting:
  118. set();
  119. break;
  120. //开启服务
  121. case R.id.open_service:
  122. startServer();
  123. break;
  124. //发送
  125. case R.id.send_out:
  126. sendText();
  127. break;
  128. default:
  129. break;
  130. }
  131. }
  132. /**
  133. * 设置
  134. */
  135. private void set() {
  136. //获取布局
  137. View setview = LayoutInflater.from(this).inflate(R.layout.port, null);
  138. //获取布局中的控件
  139. final EditText editport = (EditText) setview.findViewById(R.id.server_port);
  140. Button ensureBtn = (Button) setview.findViewById(R.id.server_ok);
  141. editport.setText(sp.getInt(PORT, 7628) + "");
  142. final android.app.AlertDialog.Builder builder = new android.app.AlertDialog.Builder(this);
  143. //设置dialog显示一个view
  144. builder.setView(setview);
  145. //dialog显示
  146. final AlertDialog dialog = builder.show();
  147. ensureBtn.setOnClickListener(new View.OnClickListener() {
  148. @Override
  149. public void onClick(View v) {
  150. String port = editport.getText().toString();
  151. if (port != null && port.length() > 0) {
  152. mServerPort = Integer.parseInt(port);//将内容转换成整数
  153. }
  154. SharedPreferences.Editor editor = sp.edit(); //SharedPreferences.Editor 简单的数据存储
  155. editor.putInt(PORT, mServerPort); //存储数据
  156. editor.commit(); //提交
  157. dialog.dismiss(); //dialog消失
  158. }
  159. });
  160. }
  161. /**
  162. * 开启服务
  163. */
  164. void startServer() {
  165. try {
  166. //开启服务、指定端口号
  167. socket = new ServerSocket(mServerPort);
  168. } catch (IOException e) {
  169. e.printStackTrace();
  170. Toast.makeText(this, "服务开启失败", Toast.LENGTH_SHORT).show();
  171. return;
  172. }
  173. startAccept();
  174. Toast.makeText(this, "服务开启", Toast.LENGTH_LONG).show();
  175. }
  176. /**
  177. * 开启SocketAcceptThread()线程
  178. */
  179. private void startAccept() {
  180. mAcceptThread = new SocketAcceptThread();
  181. mAcceptThread.start();
  182. }
  183. class SocketAcceptThread extends Thread {
  184. @Override
  185. public void run() {
  186. try {
  187. //等待客户端的连接,Accept会阻塞,直到建立连接,
  188. //所以需要放在子线程中运行。
  189. mSocket = socket.accept();
  190. //获取输入流
  191. mInStream = mSocket.getInputStream();
  192. //获取输出流
  193. mOutStream = mSocket.getOutputStream();
  194. } catch (IOException e) {
  195. e.printStackTrace();
  196. startAccept();
  197. return;
  198. }
  199. Log.i(TAG, "accept success");
  200. SocketReceive();
  201. }
  202. }
  203. private void SocketReceive() {
  204. mReceiveThread = new SocketReceiveThread();
  205. mReceiveThread.start();
  206. }
  207. class SocketReceiveThread extends Thread {
  208. private boolean threadExit = false;
  209. @Override
  210. public void run() {
  211. byte[] buffer = new byte[1024];
  212. while (threadExit == false) {
  213. try { //读取数据,返回值表示读到的数据长度。-1表示结束
  214. int count = mInStream.read(buffer);
  215. if (count == -1) {
  216. Log.i(TAG, "read read -1");
  217. startAccept();
  218. break;
  219. } else {
  220. String receiveData;
  221. receiveData = byteArrToHex(buffer);
  222. Log.i(TAG, "read buffer:" + receiveData + ",count=" + count);
  223. Message msg = new Message();
  224. msg.what = One;
  225. msg.obj = receiveData;
  226. mHandler.sendMessage(msg);
  227. }
  228. } catch (IOException e) {
  229. e.printStackTrace();
  230. }
  231. }
  232. }
  233. void threadExit() {
  234. threadExit = true;
  235. }
  236. }
  237. /**
  238. * 发送
  239. */
  240. private void sendText() {
  241. if (mSocket == null) {
  242. Toast.makeText(MainActivity.this, "没有客户端连接", Toast.LENGTH_LONG).show();
  243. return;
  244. }
  245. String str = content.getText().toString();
  246. if (str.length() == 0) {
  247. return;
  248. }
  249. Message msg = new Message();
  250. msg.what = Two;
  251. msg.obj = str;
  252. mSubThreadHandler.sendMessage(msg);
  253. }
  254. private void writeMsg(String msg) {
  255. if (msg.length() == 0 || mOutStream == null) {
  256. return;
  257. }
  258. try {
  259. //发送
  260. mOutStream.write(msg.getBytes());
  261. mOutStream.flush();
  262. } catch (IOException e) {
  263. e.printStackTrace();
  264. }
  265. }
  266. /**
  267. * 字节数组转换十六进制
  268. */
  269. public static String byteArrToHex(byte[] btArr) {
  270. char strArr[] = new char[btArr.length * 2];
  271. int i = 0;
  272. for (byte bt : btArr) {
  273. strArr[i++] = HexCharArr[bt >>> 4 & 0xf];
  274. strArr[i++] = HexCharArr[bt & 0xf];
  275. }
  276. return new String(strArr);
  277. }
  278. private void initHandlerThraed() {
  279. //创建HandlerThread实例
  280. mHandlerThread = new HandlerThread("handler_thread");
  281. //开始运行线程
  282. mHandlerThread.start();
  283. //获取HandlerThread线程中的Looper实例
  284. Looper loop = mHandlerThread.getLooper();
  285. //创建Handler与该线程绑定。
  286. mSubThreadHandler = new Handler(loop) {
  287. @Override
  288. public void handleMessage(Message msg) {
  289. Log.i(TAG, "mSubThreadHandler handleMessage thread:" + Thread.currentThread());
  290. switch (msg.what) {
  291. case Two:
  292. writeMsg((String) msg.obj);
  293. break;
  294. default:
  295. break;
  296. }
  297. }
  298. };
  299. }
  300. }

 

最后是运行效果:设置端口、开启服务、获取的数据(需要处理)

 

 

 Demo中用到的Handlerdialog对话框SharedPreferences不理解的可以参考一下我之前的发布的文章。

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

闽ICP备14008679号