热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

java实现基于TCP协议网络socket编程(C/S通信)

这篇文章主要介绍了java实现基于TCP协议网络socket编程(CS通信),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

一、前言:TCP原理简介

首先,保证文章完整性,TCP的理论原理还是需要简介一下,略显枯燥๑乛◡乛๑。

TCP(传输控制协议,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP旨在适应支持多网络应用的分层协议层次结构。也就是说,TCP是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。

以上TCP的特点,也正是与UDP的明显不同之处。UDP(用户数据报协议)是一种无连接的、不可靠的、不以字节流传输通信协议。具体区别可对比之前这篇文章:

【基于UDP协议网络Socket编程(java实现C/S通信案例) 】 [https://www.jb51.net/article/198498.htm]

接着,“三次握手”则是众所周知的一个词,是建立TCP连接的重要过程。许多文章有详细解读,本篇则是详细记录在此原理之上,使用Java实现TCP的Socket网络通信,包含C/S软件架构的程序设计,偏向实践,更加有趣!

二、Socket编程通信

本篇使用Java进行Socket编程,Java的TCP/IP套接字编程将底层的细节进行了封装,其编程模型如图:

我们自顶向下观察,基于TCP的通信,必然有服务端Server和客户端Client。

首先,建立连接。两端分别有一个套接字Socket,用于两者之间的通信。客户端向服务器发送请求,创建socket进行连接。服务端则随时监听客户端发起的请求,接收并创建裂解Socket。

其次,开始通信。服务和客户两端的输入输出流互相通信。逻辑上可理解为通信进程的双方具有两个流(输出流和输入流)。逻辑上可将两个流理解为两个通信管道的全双工通信模式,一个用于向对方发送数据,另一个用于接收对方的数据。

最后,结束通信。客户端访问服务器结束,断开连接,关闭Socket和相关资源(输入输出流等)。服务端监听客户端状态,同时关闭Socket等连接。

建立通信规则:

Server和Client之间需要约定相同的规则,保证正常通信。之后的程序设计,我们约定:

客户端连接服务器,连接成功后,服务器首先给客户端发送一条欢迎信息;

客户端程序每发送一条信息给服务器,服务器接收并回送该信息到客户端,客户端接收并显示该信息;

当客户端发送"bye",则结束对话。

三、TCP服务器端(具体代码)

第一步,创建服务端套接字。

类成员变量:ServerSocket serverSocket,监听端口号port;

  private int port =8008;//服务器监听窗口
  private ServerSocket serverSocket;//定义服务器套接字

  public TCPServer() throws IOException{
    serverSocket =new ServerSocket(port);
    System.out.println("服务器启动监听在"+port+"端口...");

  }

第二步,定义输入输出流方法:

 private PrintWriter getWriter(Socket socket) throws IOException{
    //获得输出流缓冲区的地址
    OutputStream socketOut=socket.getOutputStream();
    //网络流写出需要使用flush,这里在printWriter构造方法直接设置为自动flush
    return new PrintWriter(new OutputStreamWriter(socketOut,"utf-8"),true);
  }

  private BufferedReader getReader(Socket socket) throws IOException{
    //获得输入流缓冲区的地址
    InputStream socketIn=socket.getInputStream();
    return new BufferedReader(new InputStreamReader(socketIn,"utf-8"));
  }

 第三步,服务端核心:

//单客户版本,每次只能与一个用户建立通信连接
public void Service(){
  while (true){
    Socket socket=null;
    try {
      //此处程序阻塞,监听并等待用户发起连接,有连接请求就生成一个套接字
      socket=serverSocket.accept();

      //本地服务器控制台显示客户连接的用户信息
      System.out.println("New connection accepted:"+socket.getInetAddress());
      BufferedReader br=getReader(socket);//字符串输入流
      PrintWriter pw=getWriter(socket);//字符串输出流
      pw.println("来自服务器消息:欢迎使用本服务!");

      String msg=null;
      //此处程序阻塞,每次从输入流中读入一行字符串
      while ((msg=br.readLine())!=null){
        //如果用户发送信息为”bye“,就结束通信
        if(msg.equals("bye")){
          pw.println("来自服务器消息:服务器断开连接,结束服务!");
          System.out.println("客户端离开。");
          break;
        }
        pw.println("来自服务器消息:"+msg);
      }
    }catch (IOException e){
      e.printStackTrace();
    }finally {
      try {
        if (socket!=null)
          socket.close();//关闭socket连接以及相关的输入输出流
      }catch (IOException e){
        e.printStackTrace();
      }
    }
  }
}

 代码关键解析很清楚易懂。可以看到,服务端提供服务放到了一个While(true)里面,这是因为服务器程序需要一直运行,所以处理代码一般放在while(true)这种无限循环中,TCPServer运行一次,且自身不能终止运行,要终止它运行,只能通过强制方式(如在IDE环境强制关闭)。

四、TCP客户端(具体代码)

第一步,创建客户端套接字,定义类构造方法,实现输入输出流。

//单客户版本,每次只能与一个用户建立通信连接
public void Service(){
  while (true){
    Socket socket=null;
    try {
      //此处程序阻塞,监听并等待用户发起连接,有连接请求就生成一个套接字
      socket=serverSocket.accept();

      //本地服务器控制台显示客户连接的用户信息
      System.out.println("New connection accepted:"+socket.getInetAddress());
      BufferedReader br=getReader(socket);//字符串输入流
      PrintWriter pw=getWriter(socket);//字符串输出流
      pw.println("来自服务器消息:欢迎使用本服务!");

      String msg=null;
      //此处程序阻塞,每次从输入流中读入一行字符串
      while ((msg=br.readLine())!=null){
        //如果用户发送信息为”bye“,就结束通信
        if(msg.equals("bye")){
          pw.println("来自服务器消息:服务器断开连接,结束服务!");
          System.out.println("客户端离开。");
          break;
        }
        pw.println("来自服务器消息:"+msg);
      }
    }catch (IOException e){
      e.printStackTrace();
    }finally {
      try {
        if (socket!=null)
          socket.close();//关闭socket连接以及相关的输入输出流
      }catch (IOException e){
        e.printStackTrace();
      }
    }
  }
}

第二步,实现网络通信发送和接收方法。

  public void send(String msg){
    //输出字符流,由socket调用系统底层函数,经网卡发送字节流
    pw.println(msg);
  }

  public String receive(){
    String msg=null;
    try {
      //从网络输入字符流中读取信息,每次只能接受一行信息
      //不够一行时(无行结束符),该语句阻塞
      //直到条件满足,程序往下运行
      msg=br.readLine();
    }catch (IOException e){
      e.printStackTrace();
    }
    return msg;
  }

 第三步,定义网络连接关闭方法供外部调用。

 public void close(){
    try {
      if (socket!=null)
        socket.close();
    }catch (IOException e){
      e.printStackTrace();
    }
  }

TCP连接的释放也有“四次握手”一说,必须经过2MSL后才真正释放。具体过程如下图:

五、通信效果演示

GIF动图演示:

六、“创意”机器人:价值一个亿的AI核心代码(具体代码)

这部分我们要实现“聊天机器人”,效果这样:

是不是迫不及待想知道如何实现呢!堪称“价值一个亿的AI核心代码”!!??

就这样实现了!

 不卖关子了,就一行代码!

msg=msg.replace("?","!").replace("?","!").replace("吗","").replace("吗?","");

具体想实现机器人如何回复可以自行调整代码。

七、最后

本篇则是详细记录在此原理之上,使用Java实现TCP的Socket网络通信,包含C/S软件架构的程序设计,偏向实践,更加有趣!仔细阅读的朋友可以发现,在服务器端核心部分,有一行注释说明了该程序只支持单用户,也就是单线程通信,可以尝试一下,如果再开一个客户端连接该服务,是否因为单线程阻塞程序卡住了。

这个问题关键就在于:服务器和客户端互相约定通信规则,否则就可能有问题,例如,如果服务器在一个客户端连接成功后,并没有一条信息发送给客户端,客户端的读取欢迎信息的语句无法读取到内容,就被阻塞住,由于是单线程,甚至整个程序都会被卡住。要解决这个问题,等待更新下一篇!

另外,UI界面的设计可参考上一篇博客:【基于UDP协议网络Socket编程(java实现C/S通信案例) 】 [https://www.jb51.net/article/198498.htm]

到此这篇关于java实现基于TCP协议网络socket编程(C/S通信)的文章就介绍到这了,更多相关java TCP协议socket编程内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • TCP三次握手过程详解与图示解析
    本文详细解析了TCP三次握手的过程,并通过图示清晰展示了各个状态的变化。同时,文章还介绍了四次挥手的图解,解释了在TIME_WAIT状态中,客户端最后一次发送的ACK包的作用和重要性。 ... [详细]
  • REST与RPC:选择哪种API架构风格?
    在探讨REST与RPC这两种API架构风格的选择时,本文首先介绍了RPC(远程过程调用)的概念。RPC允许客户端通过网络调用远程服务器上的函数或方法,从而实现分布式系统的功能调用。相比之下,REST(Representational State Transfer)则基于资源的交互模型,通过HTTP协议进行数据传输和操作。本文将详细分析两种架构风格的特点、适用场景及其优缺点,帮助开发者根据具体需求做出合适的选择。 ... [详细]
  • MicrosoftDeploymentToolkit2010部署培训实验手册V1.0目录实验环境说明3实验环境虚拟机使用信息3注意:4实验手册正文说 ... [详细]
  • 最详尽的4K技术科普
    什么是4K?4K是一个分辨率的范畴,即40962160的像素分辨率,一般用于专业设备居多,目前家庭用的设备,如 ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • 大家好,我是李白。本文将分享一个从零开始的全栈项目,涵盖了设计、前端、后端和服务端的全面学习过程。通过这个项目,我希望能够帮助初学者更好地理解和掌握全栈开发的技术栈。 ... [详细]
  • javascript分页类支持页码格式
    前端时间因为项目需要,要对一个产品下所有的附属图片进行分页显示,没考虑ajax一张张请求,所以干脆一次性全部把图片out,然 ... [详细]
  • 本章介绍了TCP/IP协议族中的链路层,其主要功能是为IP模块发送和接收IP数据报。链路层还支持一些辅助性协议,如ARP。此外,本文详细探讨了不同类型的链路层技术及其应用。 ... [详细]
  • 本文介绍了如何利用HTTP隧道技术在受限网络环境中绕过IDS和防火墙等安全设备,实现RDP端口的暴力破解攻击。文章详细描述了部署过程、攻击实施及流量分析,旨在提升网络安全意识。 ... [详细]
  • 本文介绍了如何通过Sybase Central连接到示例数据库,并查看其中的表和其他对象。主要内容包括启动Sybase Central、建立连接、查看表列表及表的具体信息。 ... [详细]
  • 小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限
    小王详解:内部网络中最易理解的NAT原理剖析,挑战你的认知极限 ... [详细]
  • ROS主机与从机之间的通信原理及机制分析
    本文深入探讨了ROS(Robot Operating System)主机与从机之间的通信原理及机制。通过分析ROS网络架构,详细阐述了节点间的通信方式、消息传递流程以及数据同步机制。此外,还介绍了ROS中常用的通信模式,如发布/订阅、服务调用和参数服务器,为开发者提供了全面的技术指导。 ... [详细]
  • 当前,众多初创企业对全栈工程师的需求日益增长,但市场中却存在大量所谓的“伪全栈工程师”,尤其是那些仅掌握了Node.js技能的前端开发人员。本文旨在深入探讨全栈工程师在现代技术生态中的真实角色与价值,澄清对这一角色的误解,并强调真正的全栈工程师应具备全面的技术栈和综合解决问题的能力。 ... [详细]
  • 从用户转型为开发者:一场思维升级的旅程 | 专访 StarRocks Committer 周威
    从用户转变为开发者,不仅是一次角色的转换,更是一场深刻的思维升级之旅。本次专访中,StarRocks Committer 周威分享了他如何在这一过程中逐步提升技术能力与思维方式,为开源社区贡献自己的力量。 ... [详细]
  • 点云技术初探(三):PCL基础知识与学习路径指南本文首先介绍了点云库(PCL)的基本概念,PCL是一个在前人点云研究成果基础上发展而来的大型跨平台开源C++编程库,旨在为点云数据处理提供全面的支持。文章详细阐述了PCL的核心功能及其在三维数据处理、特征提取、分割与配准等方面的应用,并为初学者提供了系统的学习路径和资源推荐,帮助读者快速掌握PCL的使用方法。 ... [详细]
author-avatar
男人吧总负责人千金
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有