TCP Socket通信是一种比较常用的基于连接的网络通信方式。本文通过Java实现TCP Socket通信,并将其用于计算机端,Android手机端,硬件设备端,同时做到代码规范化,实现代码最大化复用。

| 本文代码可在GitHub下载,建议对照源码阅读文章 https://github.com/IVanMissAya/tcp_server

TCP连接的建立

客户端和服务器间通过 三次握手 建立TCP连接。在Java中,连接建立完成后,服务器端和客户端分别获取到一个Socket实例,之后就可以通过这个Socket实例进行通信。服务器端和客户端使用不同的方法获取Socket实例。

  1. 服务器端

    在服务器端,通过ServerSocket实现对指定端口的监听,代码如下。其中port为int型端口数值,取值065535,01024为系统保留端口,这里取值1234。如果发生错误将会抛出异常。

    int port = 1234;
    ServerSocket server = new ServerSocket(port);
    

    通过ServerSocket.accept()方法接受客户端连接。这个方法是阻塞的,从调用时开始监听端口,直到客户端连接建立时,执行结束并返回Socket实例。连接建立失败会抛出异常。

    Socket socket = server.accept();
    
  2. 客户端

    客户端直接通过实例化的形式,产生Socket实例。实例化的过程中,尝试连接指定的服务器主机。连接成功则实例化完成,连接失败则抛出异常。hostIP为主机的IP地址,port为端口号,和服务器主机监听的端口号保持一致。

    String hostIP = "127.0.0.1";
    int port = 1234;
    Socket socket = new Socket(hostIP, port);
    

连接的建立过程

以上代码的执行顺序是:

  • 服务器端实例化ServerSocket:new ServerSocket(port);
  • 服务器端执行accept(),监听指定端口,此方法阻塞等待客户端连接:server.accept();
  • 客户端实例化Socket实例,尝试连接服务器:new Socket(hostIP, port);
  • TCP三次握手成功,服务器端的accept()返回Socket实例,同时客户端的Socket实例化成功。

Socket的读写

以收发字符串为例来说明Socket的读写。

向Socket对象写入数据,则会发送至TCP连接的另一方。这个操作在服务器端和客户端是一样的。可通过获取Socket的输出流来写入UTF8格式编码的字符串,代码如下。写入完成后,就会被发送到连接的另一端。

private DataOutputStream out;
out = new DataOutputStream(socket.getOutputStream());
String s = "Test";
out.writeUTF(s);
out.flush();

在接收端,通过获取Socket的输入流,就可以读取字符串数据,代码如下。readUTF()方法是阻塞的,直到对方发送完一个字符串,该方法才会执行结束并返回收到的字符串。如果连接中断,或强制关闭Socket的输入流,即执行socket.shutdownInput(),该方法会抛出异常。

private DataInputStream in;
in = new DataInputStream(socket.getInputStream());
String s = in.readUTF();

在建立了TCP连接后,由于无法确定对方的数据发送时间,为了保证及时接收到数据,通过一个新线程不断调用in.readUTF()方法读取数据(相当于轮询法);并在接收到数据后回调相关函数,对数据进行处理。

TCP连接的断开

TCP Socket连接是双向的,通过 四次挥手 的方式断开,双方分别调用Socket.close()方法断开连接。连接断开的过程中,一般一方A先断开连接,另一方B发现A断开连接后,也断开连接。为方便表述,将先断开连接的一方A称为“主动断开连接”;后断开的一方B,则为“被动断开连接”。

在一方B阻塞执行in.readUTF()方法时,如果对方A主动断开Socket连接,这个方法会抛出异常。从而在B处理异常时,可以被动的断开这边的连接。

为保证主动断开连接的一方不会阻塞在in.readUTF()方法中,需要先执行socket.shutdownInput()。所以主动断开连接的代码如下。

socket.shutdownInput();
in.close();
socket.close();

被动断开连接的一方,在捕获到in.readUTF()的异常后,断开Socket连接。

try {String s = in.readUTF();
} catch (IOException e) {// 连接被断开(被动)try {in.close();socket.close();in = null;socket = null;} catch (IOException e) {e.printStackTrace();}
}

SocketTransceiver的实现

考虑到在服务器端和客户端,Socket对象的操作是完全一样的,所以实现了一个SocketTransceiver(收发器),实现对Socket的直接操作,其他代码则通过SocketTransceiver间接操作Socket对象实现数据收发、断开连接等。

SocketTransceiver实现的功能有:

  • 开启新线程不断查询Socket是否收到数据;
  • 将字符串、文件等类型的数据进行打包,并通过Socket发送;
  • 从Socket接收数据,并自动解析出数据(字符串、文件等),接收完成后回调相应的方法;
  • 在发生错误、连接被动断开时,自动断开连接并进行相关处理,并回调相应方法。
    SocketTransceiver.class 使用抽象类实现,回调方法是抽象的,实例化时对抽象方法进行实现,处理回调。完整代码见附件。

TcpServer的实现

TcpServer为TCP Socket服务器端程序。为了让服务器能同时接受并处理来自多个客户端的TCP连接请求:

  • TcpServer中用一个监听线程对端口进行监听,即阻塞执行server.accept()方法,等待接受客户端连接;
  • 服务器端每次与一个客户端建立连接,即accept()方法执行结束并返回一个Socket对象,就会用一个SocketTransceiver对这个Socket进行操作;
  • 连接建立后,监听线程再次执行server.accept()方法,继续监听端口并等待下一个连接;
  • 服务器端有一个List,保存当前连接的每个客户端对应的SocketTransceiver对象,在需要时可取出并进行操作。

TcpClient的实现

TcpClient为TCP Socket客户端程序。主要工作是进行Socket的连接,并利用SocketTransceiver对Socket进行操作。

另附 windows 下tcp 测试工具

  1. sokit 是一款开源免费的 TCP / UDP 测试(调试)工具, 可以用来接收,发送或转发TCP/UDP数据包。 下载地址: http://sqdownd.onlinedown.net/down/sokit-1.3-win32-chs.zip

  2. TCPUDP测试工具用于开发网络通讯程序时,在服务器或客户端测试TCP/UDP通讯连接和测试数据的接收和发送情况。 下载地址: http://fastsoft.onlinedown.net/down/TCPUDPDebug102_Setup.exe

基于Java的TCP Socket通信详解相关推荐

  1. 基于Java的TCP Socket通信详解(计算机端/Android手机端)

    TCP Socket通信是一种比较常用的基于连接的网络通信方式.本文通过Java实现TCP Socket通信,并将其用于计算机端.Android手机端,同时做到代码规范化,实现代码最大化复用. 本文代 ...

  2. android传递socket对象,Android Socket通信详解

    一.Socket通信简介 Android与服务器的通信方式主要有两种,一是Http通信,一是Socket通信.两者的最大差异在于,http连接使用的是"请求-响应方式",即在请求时 ...

  3. 基于Java NIO的Socket通信

    基于Java NIO的Socket通信 Java NIO模式的Socket通信,是一种同步非阻塞IO设计模式,它为Reactor模式实现提供了基础. 下面看看,Java实现的一个服务端和客户端通信的例 ...

  4. stringtokenizer java_基于Java中的StringTokenizer类详解(推荐)

    StringTokenizer是字符串分隔解析类型,属于:Java.util包. 1.StringTokenizer的构造函数 StringTokenizer(String str):构造一个用来解析 ...

  5. C++ socket通信详解

    Socket是什么 Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面, ...

  6. java ws协议_基于java实现websocket协议过程详解

    最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向 ...

  7. Java网络编程和NIO详解1:JAVA 中原生的 socket 通信机制

    JAVA 中原生的 socket 通信机制 转载自:https://github.com/jasonGeng88/blog 当前环境 jdk == 1.8 知识点 socket 的连接处理 IO 输入 ...

  8. Modbus通信从入门到精通_2_Modbus TCP通信详解及仿真(搭建ModbusTCP仿真环境:创建虚拟PLC并进行ModbusTCP通讯;寄存器与PLC中映射关系;适合理解如何编写上位机)

    本篇将会以西门子PLC软件搭建ModbusTCP仿真环境,并通过仿真环境,介绍基础知识及模拟实际应用中写一个简单的通信读取PLC数据方法,并简介了编写上位机的方法. 文章目录 1. 搭建ModbusT ...

  9. java tcp read_【Java TCP/IP Socket】TCP Socket通信中由read返回值造成的的死锁问题(含代码)(转)...

    书上示例 在第一章<基本套接字>中,作者给出了一个TCP Socket通信的例子--反馈服务器,即服务器端直接把从客户端接收到的数据原原本本地反馈回去. 书上客户端代码如下: 书上的服务器 ...

  10. 【Java TCP/IP Socket】TCP Socket通信中由read返回值造成的的死锁问题(含代码)(转)...

    书上示例 在第一章<基本套接字>中,作者给出了一个TCP Socket通信的例子--反馈服务器,即服务器端直接把从客户端接收到的数据原原本本地反馈回去. 书上客户端代码如下: 1 2 3 ...

最新文章

  1. PHP 函数 ignore_user_abort定时执行任务的实现
  2. kubernetes dashboard backend源码剖析
  3. BSP UI Workbench double click component and see view list
  4. c语言中输出9个空格,新人提问:如何将输出时每行最后一个空格删除
  5. 计算机应用属于工程与工程经济类,计算机及信息技术和电子技术应用哪种属于工程类或工程经济类专业?...
  6. 编程—休息片刻的好处
  7. maven创建java,Maven创建Java项目
  8. 【Unity】Geometry Shader实现
  9. 图数据库JanusGraph入门(一)JanusGraph初识
  10. 蓝桥杯真题(python)+B组真题+解题链接
  11. 某网站字幕加密的wasm分析
  12. Autojs实战教程---番茄免费小说Apk文件和源码
  13. 如何用Python解析JSON数据
  14. springboot整合author2
  15. 用计算机处理表格信息,用计算机处理数据
  16. 个人电脑php网站搭建,如何在本地电脑搭建自己网站的流程(图文教程)
  17. 海胆状金纳米颗粒,粒径:150-200nm|银包金纳米颗粒 粒径:5-200nm|碳包金纳米颗粒 粒径:可定制
  18. php 发socket数据库,php socket连接数据库
  19. Windows使用SSH登录VM虚拟机
  20. Symbol - 看似平凡的Symbol其实我们每天都在用 - 字符串操作

热门文章

  1. php 3.2 下载,PHPWind
  2. 破解Access(*.mdb)目前所有版本的密码
  3. 下载站mime属性设置(让文件可下载)
  4. 10分钟搭建树莓派NAS私有云和KODI影音播放系统 (2)---软硬搭配干活不累
  5. cocosbuilder3.0使用小记
  6. 中国生物医药产业集群产业战略布局及运营管理模式分析报告2021-2027年
  7. 如何更新一台计算机的驱动程序,怎样更新电脑最新驱动程序? -电脑资料
  8. CSS标准颜色参考表
  9. RHadoop实践系列文章
  10. 统计学基础知识有哪些?看这一篇就够了