热门标签 | 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编程内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 随着网络安全威胁的不断演变,电子邮件系统成为攻击者频繁利用的目标。本文详细探讨了电子邮件系统中的常见漏洞及其潜在风险,并提供了专业的防护建议。 ... [详细]
  • 本文介绍如何在现有网络中部署基于Linux系统的透明防火墙(网桥模式),以实现灵活的时间段控制、流量限制等功能。通过详细的步骤和配置说明,确保内部网络的安全性和稳定性。 ... [详细]
  • 本文介绍了如何在具备多个IP地址的FTP服务器环境中,通过动态地址端口复用和地址转换技术优化网络配置。重点讨论了2Mb/s DDN专线连接、Cisco 2611路由器及内部网络地址规划。 ... [详细]
  • 如何配置Unturned服务器及其消息设置
    本文详细介绍了Unturned服务器的配置方法和消息设置技巧,帮助用户了解并优化服务器管理。同时,提供了关于云服务资源操作记录、远程登录设置以及文件传输的相关补充信息。 ... [详细]
  • 网络攻防实战:从HTTP到HTTPS的演变
    本文通过一系列日记记录了从发现漏洞到逐步加强安全措施的过程,探讨了如何应对网络攻击并最终实现全面的安全防护。 ... [详细]
  • 解决MongoDB Compass远程连接问题
    本文记录了在使用阿里云服务器部署MongoDB后,通过MongoDB Compass进行远程连接时遇到的问题及解决方案。详细介绍了从防火墙配置到安全组设置的各个步骤,帮助读者顺利解决问题。 ... [详细]
  • 本文详细探讨了HTTP 500内部服务器错误的成因、解决方案及其在Web开发中的影响。通过对具体案例的分析,帮助读者理解并解决此类问题。 ... [详细]
  • 本文介绍了如何使用PHP代码实现微信平台的媒体素材上传功能,详细解释了API接口的使用方法和注意事项,确保文件路径正确以避免常见的错误。 ... [详细]
  • 使用Vultr云服务器和Namesilo域名搭建个人网站
    本文详细介绍了如何通过Vultr云服务器和Namesilo域名搭建一个功能齐全的个人网站,包括购买、配置服务器以及绑定域名的具体步骤。文章还提供了详细的命令行操作指南,帮助读者顺利完成建站过程。 ... [详细]
  • 在现代网络环境中,两台计算机之间的文件传输需求日益增长。传统的FTP和SSH方式虽然有效,但其配置复杂、步骤繁琐,难以满足快速且安全的传输需求。本文将介绍一种基于Go语言开发的新一代文件传输工具——Croc,它不仅简化了操作流程,还提供了强大的加密和跨平台支持。 ... [详细]
  • 使用Python在SAE上开发新浪微博应用的初步探索
    最近重新审视了新浪云平台(SAE)提供的服务,发现其已支持Python开发。本文将详细介绍如何利用Django框架构建一个简单的新浪微博应用,并分享开发过程中的关键步骤。 ... [详细]
  • 从零开始构建完整手机站:Vue CLI 3 实战指南(第一部分)
    本系列教程将引导您使用 Vue CLI 3 构建一个功能齐全的移动应用。我们将深入探讨项目中涉及的每一个知识点,并确保这些内容与实际工作中的需求紧密结合。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
  • 通过与阿里云的合作,牛客网成功解决了跨国视频面试中的网络卡顿问题,为求职者和面试官提供了更加流畅的沟通体验。 ... [详细]
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社区 版权所有