【网络编程】| 搭建控制台通信demo

news2025/2/23 23:38:34

目录

    • 🦁TCP通信实现原理
    • 🦁TCP单向通信
      • 创建服务端
      • 创建客户端
    • 🦁TCP双向通信
      • 创建服务端
      • 创建客户端
    • 🦁创建点对点的聊天应用
      • 创建发送消息线程和接收消息线程
      • 创建服务端
      • 创建客户端
    • 🦁优化点对点聊天应用

🦁TCP通信实现原理

前边我们提到TCP协议是面向的连接的,在通信时客户端与服务器端必须建立连接。在网络通讯中,第一次主动发起通讯的程序被称作客户端(Client)程序,简称客户端,而在第一次通讯中等待连接的程序被称作服务器端(Server)程序,简称服务器。一旦通讯建立,则客户端和服务器端完全一样,没有本质的区别

请求响应模式:

  • Socket类:发送TCP消息。
  • ServerSocket类:创建服务器

**套接字Socket是一种进程间的数据交换机制。**套接字与主机地址和端口地址相关联。主机地址就是客户端或服务器程序所在的主机的IP地址。端口地址是指客户端或服务器程序使用的主机的通信端口。(使用输入输出流进行通信)

TCP/IP套接字是最可靠的双向流协议,使用TCP/IP可以发送任意数量的数据

image-20230523173102168

通过 Socket的编程顺序

  1. 创建服务器ServerSocket,在创建时,定义ServerSocket的监听端口(在这个端口接收客户端发来的消息)

  2. ServerSocket调用accept()方法,使之处于阻塞状态。

  3. 创建客户端Socket,并设置服务器的IP及端口。

  4. 客户端发出连接请求,建立连接。

  5. 分别取得服务器和客户端Socket的InputStream和OutputStream。

  6. 利用Socket和ServerSocket进行数据传输。

  7. 关闭流及Socket。

🦁TCP单向通信

单向通信是指通信双方中,一方固定为发送端,一方则固定为接收端。

创建服务端

public class OneWaySocketServer {
  public static void main(String[] args) {
    System.out.println("服务端启动,开始监听。。。。。");
    try(ServerSocket serverSocket = new ServerSocket(8888);
      //监听8888端口,获与取客户端对应的Socket对象
      Socket socket = serverSocket.accept();
      //通过与客户端对应的Socket对象获取输入流对象
      BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      //通过与客户端对应的Socket对象获取输出流对象
      PrintWriter pw = new PrintWriter(socket.getOutputStream())){
      System.out.println("连接成功!");
      while(true){
        //读取客户端发送的消息
        String str = br.readLine();
        System.out.println("客户端说:"+str);
        if("exit".equals(str)){
          break;
         }
        pw.println(str);
        pw.flush();
       }
     }catch(Exception e){
      e.printStackTrace();
      System.out.println("服务端启动失败。。。。。");
     }
   }
}

创建客户端

public class OneWaySocketClient {
  public static void main(String[] args) {
    //获取与服务端对应的Socket对象
    try(Socket socket = new Socket("127.0.0.1",8888);
      //创建键盘输入对象
      Scanner scanner = new Scanner(System.in);
      //通过与服务端对应的Socket对象获取输出流对象
      PrintWriter pw = new PrintWriter(socket.getOutputStream());
      //通过与服务端对应的Socket对象获取输入流对象
      BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))){

      while(true){
        //通过键盘输入获取需要向服务端发送的消息
        String str = scanner.nextLine();
        
        //将消息发送到服务端
        pw.println(str);
        pw.flush();

        if("exit".equals(str)){
          break;
         }
          
        //读取服务端返回的消息
        String serverInput = br.readLine();
        System.out.println("服务端返回的:"+serverInput);


       }
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

tips:

​ 都是先运行服务端再运行客户端哦!

🦁TCP双向通信

双向通信是指通信双方中,任何一方都可为发送端,任何一方都可为接收端。

创建服务端

public class TwoWaySocketServer {
  public static void main(String[] args) {
    System.out.println("服务端启动!监听端口8888。。。。");
    try(ServerSocket serverSocket = new ServerSocket(8888);
      Socket socket = serverSocket.accept();
      //创建键盘输入对象
      Scanner scanner = new Scanner(System.in);
      //通过与客户端对应的Socket对象获取输入流对象
      BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      //通过与客户单对应的Socket对象获取输出流对象
      PrintWriter pw = new PrintWriter(socket.getOutputStream());){


      while(true){
        //读取客户端发送的消息
        String str = br.readLine();
        System.out.println("客户端说:"+str);
        String keyInput = scanner.nextLine();
        //发送到客户端
        pw.println(keyInput);
        pw.flush();
       }
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

创建客户端

public class TwoWaySocketClient {
  public static void main(String[] args) {
    try(Socket socket = new Socket("127.0.0.1", 8888);
      //创建键盘输入对象
      Scanner scanner = new Scanner(System.in);
      //通过与服务端对应的Socket对象获取输入流对象
      BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
      //通过与服务端对应的Socket对象获取输出流对象
      PrintWriter pw = new PrintWriter(socket.getOutputStream());){


      while (true) {
        String keyInput = scanner.nextLine();
        pw.println(keyInput);
        pw.flush();
        String input = br.readLine();
        System.out.println("服务端说:" + input);
       }
     } catch (Exception e) {
      e.printStackTrace();
     }
   }
}

这种由于两个端都是在同一个线程上,所以不能随意发送信息,必须等待一个端接收到信息之后另一个端才能继续发送。

🦁创建点对点的聊天应用

可以像聊天那样随意发送消息,实际上就是另起发送消息和接收消息线程,这样发送和接收就可以同步进行。

创建发送消息线程和接收消息线程

/**
 * 发送消息线程
 */
class Send extends Thread{
  private Socket socket;
  public Send(Socket socket){
    this.socket = socket;
   }
    
  @Override
  public void run() {
    this.sendMsg();
   }
    
  /**
   * 发送消息
   */
  private void sendMsg(){
    //创建Scanner对象
    try(Scanner scanner = new Scanner(System.in);
      //创建向对方输出消息的流对象
      PrintWriter pw = new PrintWriter(this.socket.getOutputStream());){


      while(true){
        String msg = scanner.nextLine();
        pw.println(msg);
        pw.flush();
       }
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

/**
 * 接收消息的线程
 */
class Receive extends Thread{
  private Socket socket;
  public Receive(Socket socket){
    this.socket = socket;
   }
  @Override
  public void run() {
    this.receiveMsg();


   }
  /**
   * 用于接收对方消息的方法
   */
  private void receiveMsg(){
    //创建用于接收对方发送消息的流对象
    try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));){


      while(true){
        String msg = br.readLine();
        System.out.println("他说:"+msg);
       }
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

创建服务端

public class ChatSocketServer {
  public static void main(String[] args) {

    try(ServerSocket serverSocket = new ServerSocket(8888);){
      System.out.println("服务端启动,等待连接。。。。。");
      Socket socket = serverSocket.accept();
      System.out.println("连接成功!");
      new Send(socket).start();
      new Receive(socket).start();
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

创建客户端

/**
 * 用于发送消息的线程类
 */
class ClientSend extends Thread{
  private Socket socket;
  public ClientSend(Socket socket){
    this.socket = socket;
   }
    
  @Override
  public void run() {
    this.sendMsg();
   }
  /**
   * 发送消息
   */
  private void sendMsg(){
    //创建Scanner对象
    try(Scanner scanner = new Scanner(System.in);
      //创建向对方输出消息的流对象
      PrintWriter pw = new PrintWriter(this.socket.getOutputStream());){

      while(true){
        String msg = scanner.nextLine();
        pw.println(msg);
        pw.flush();
       }
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}
/**
 * 用于接收消息的线程类
 */
class ClientReceive extends Thread{
  private Socket socket;
  public ClientReceive(Socket socket){
    this.socket = socket;
   }
  @Override
  public void run() {
    this.receiveMsg();
   }
  /**
   * 用于接收对方消息的方法
   */
  private void receiveMsg(){
    //创建用于接收对方发送消息的流对象
    try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));){
      while(true){
        String msg = br.readLine();
        System.out.println("他说:"+msg);
       }
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

public class ChatSocketClient {
  public static void main(String[] args) {
    try {
      Socket socket = new Socket("127.0.0.1", 8888);
      System.out.println("连接成功!");
      new ClientSend(socket).start();
      new ClientReceive(socket).start();
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

🦁优化点对点聊天应用

前面的案例中,客户端和服务器都有大量重复代码(发送消息和接收消息),其实在网络编程中,编写客户端和服务器唯一的区别就是在实例化socket的时候不一样(一个是实例化ServerSocket,指定监听端口,通过ServerSocket获取客户端的socket,一个是实例化Socket),其它部分都是一致的,所以我们可以把接收信息线程和发送消息线程提取出来,客户端和服务端写在同一个实例里面,通过判断用户输入的信息来执行实例化服务器还是客户端。

/**
 * 发送消息线程
 */
class Send extends Thread{
  private Socket socket;
  private Scanner scanner;
  public Send(Socket socket,Scanner scanner){
    this.socket = socket;
    this.scanner = scanner;
   }
    
  @Override
  public void run() {
    this.sendMsg();
   }
    
  /**
   * 发送消息
   */
  private void sendMsg(){
    //创建向对方输出消息的流对象
    try(PrintWriter pw = new PrintWriter(this.socket.getOutputStream())){
      
      while(true){
        String msg = scanner.nextLine();
        pw.println(msg);
        pw.flush();
       }
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}

/**
 * 接收消息的线程
 */
class Receive extends Thread{
  private Socket socket;
  public Receive(Socket socket){
    this.socket = socket;
   }
  @Override
  public void run() {
    this.receiveMsg();
   }
  /**
   * 用于接收对方消息的方法
   */
  private void receiveMsg(){
    //创建用于接收对方发送消息的流对象
    try(BufferedReader br = new BufferedReader(new InputStreamReader(this.socket.getInputStream()))){


      while(true){
        String msg = br.readLine();
        System.out.println("他说:"+msg);
       }
     }catch(Exception e){
      e.printStackTrace();
     }
   }
}
public class GoodTCP {
  public static void main(String[] args) {
    Scanner scanner = null;
    ServerSocket serverSocket = null;
    Socket socket = null;
    try{
      scanner = new Scanner(System.in);
      System.out.println("请输入:server,<port> 或者:<ip>,<port>");
      String str = scanner.nextLine();
      String[] arr = str.split(",");
      if("server".equals(arr[0])){
        //启动服务端
        System.out.println("TCP Server Listen at "+arr[1]+" .....");
        serverSocket = new ServerSocket(Integer.parseInt(arr[1]));
        socket = serverSocket.accept();
        System.out.println("连接成功!");
       }else{
        //启动客户端
        socket = new Socket(arr[0],Integer.parseInt(arr[1]));
        System.out.println("连接成功!");
       }
      //启动发送消息的线程
      new Send(socket,scanner).start();
      //启动接收消息的线程
      new Receive(socket).start();
     }catch(Exception e){
      e.printStackTrace();
     }finally{
      if(serverSocket != null){
        try {
          serverSocket.close();
         } catch (IOException e) {
          e.printStackTrace();
         }
       }
     }
   }
}

image-20230524091713406

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/561951.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

既然有了IP地址,为什么还需要MAC地址?两者到底有啥区别,深入分析后终于明白了!

在计算机网络中&#xff0c;IP地址和MAC地址是两个最基本的概念。IP地址在互联网中是用于标识主机的逻辑地址&#xff0c;而MAC地址则是用于标识网卡的物理地址。虽然它们都是用于标识一个设备的地址&#xff0c;但是它们的作用和使用场景是不同的。 IP地址是在网络层&#xff…

Windows下安装搭建MQTT服务器

服务器常用的有emqx,还有apache apolle&#xff0c;这里用的是emqx 服务端以及客户端可以使用MQTTnet&#xff08;NuGet包&#xff09; 一、MQTT服务器&#xff08; emqx &#xff09;搭建 1. 下载服务器MQTT Broker 从 https://www.emqx.io/cn/mqtt/public-mqtt5-broker下载…

Wi-Fi 6为啥那么快?

Wi-Fi 6&#xff08;802.11ax&#xff09;是当前最新的无线局域网标准&#xff0c;它带来了许多重要的改进和性能提升。本文将详细介绍Wi-Fi 6的速度和性能&#xff0c;以及与前一代标准相比的差异。 Wi-Fi 6的速度提升 相比于前一代标准&#xff08;Wi-Fi 5或802.11ac&#x…

fNIRS最新研究 | 脑间和脑内耦合对运动同步的差异贡献

导读 人类大脑支持行为的一个基本特征是它在脑区之间建立连接的能力。一种有前景的方法认为&#xff0c;在社交行为中&#xff0c;大脑区域不仅与大脑内的其他脑区建立连接&#xff0c;而且还与互动伙伴的其他脑区协调活动。本文探索脑间和脑内耦合是否对运动同步有不同的贡献…

设计模式之【责任链模式】,路铺好了,你走不走?

文章目录 一、什么是责任链模式1、状态模式与责任链模式的区别2、责任链模式使用场景3、责任链模式的优缺点4、责任链模式的角色 二、实例1、责任链模式的一般写法&#xff08;1&#xff09;一般写法&#xff08;2&#xff09;一般写法-使用建造者模式进阶&#xff08;3&#x…

nacos配置加载顺序

spring boot 调整日志打印情况 logging:level:com:alibaba:cloud: debug # nacos: debugorg:springframework:context: debugcloud: debug # boot: debug 项目启动时打印了 properties search order:PROPERTIES->JVM->ENV->DEFAULT_SETTING 查看具体代…

股票配资交易系统【实盘】

股票配资系统建设&#xff0c;本文档主要针对实盘股票配资系统。 股票配资交易系统主要包含三部分&#xff1a;App客户端、交易程序服务端、管理后台 App客户端 app客户端是原生应用&#xff0c;非H5生成。客户端主要功能是承接用户的股票订单委托、查询、用户资金转入&#x…

2023.5.12解决Ubuntu中ens33没有ip

在Ubtuntu中的ens33没有ip 如果Ubuntu版本过高 sudo netplan apply如果是Ubuntu 16.04及更早版本 sudo vi /etc/systemd/resolved.conf具体情况如下图所示 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopbac…

java版企业工程项目管理系统 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离 功能清单

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

iVX和其它低代码的平台的区别,“低代码/无代码”分三类

前言 这个图非常认真地对整个“低代码”领域做了严格的分类&#xff0c;这个里面并没有把只针对工作流或单纯BI的工具产品划分进去&#xff0c;主要是这一类&#xff0c;在我个人理解里面更像“SaaS”&#xff0c;也就是增强版SaaS产品&#xff0c;这类产品也主要是给业务人员使…

SpringCloud学习-实用篇04

以下内容的代码可见&#xff1a;SpringCloud_learn/day04 1.初始MQ 同步通讯和异步通讯 微服务间通讯有同步和异步两种方式&#xff0c;同步通讯就像打电话需要实时响应&#xff0c;异步通讯就像发邮件不需要马上回复。两种方式各有优劣&#xff0c;比如打电话能立即得到响应&a…

STM8使用pwm接口调试GDS06灰尘传感器

背景 刚好有项目使用GDS06这款传感器&#xff0c;这里简单做个记录。 GDS06接口如下&#xff0c;这里支持串口和PWM的输出到MCU&#xff0c;由于项目采用STM8S003F3P6&#xff0c;资源极其有限。 所以硬件设计的时候&#xff0c;就考虑采用PWM的接口方式&#xff0c;这样只是…

安科瑞有源电力滤波器的设计原理及应用前景

安科瑞 徐浩竣 江苏安科瑞电器制造有限公司 zx acrelxhj 摘要&#xff1a;该文介绍了有源电力滤波器的工作原理和基本控制方法&#xff0c;并阐述有源电力滤波器的现状及发展前景等等。 关键词&#xff1a;有源电力滤波器&#xff1b;谐波&#xff1b;工作原理&#xff1b;…

方案绞尽脑汁想不出?试试这款AI代写方案

一份计划方案&#xff0c;往往是工作进行下去的核心环节&#xff0c;需要考虑很多因素和变量&#xff0c;在某些情况下&#xff0c;可能没有足够的信息来制定有效的方案。这可能会导致需要额外的研究和调查&#xff0c;以便了解更多关于问题的信息&#xff0c;这将延长制定方案…

侧边拖拉功能

一、页面 <div class"resize-handle" mousedown"startResizing">⋮</div> 二、js data() {return {showSideBar: true,leftPaneWidth: 63, // 左侧区域的初始宽度isResizing: false, // 标记是否正在调整大小startX: 0, // 调整大小开始时的…

Spring AOP 中的切点是什么?如何定义切点?

Spring AOP 中的切点是什么&#xff1f;如何定义切点&#xff1f; 什么是切点&#xff1f; 在 Spring AOP 中&#xff0c;切点&#xff08;Pointcut&#xff09;是指一组连接点&#xff08;Join Point&#xff09;的集合。连接点是程序执行过程中的某个特定点&#xff0c;例如…

初识SpringMVC -- SpringMVC入门保姆级教程(一)

文章目录 前言一、初识SpringMVC1.认识SpringMVC2.SpringMVC入门案例3.SpringMVC开发的一般步骤4.入门案例涉及的知识点5.入门案例工作流程 总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便日后回顾。当然&#xff0c;如果能…

阿里云服务器端口怎么打开?详细教程一步步

阿里云服务器端口怎么打开&#xff1f;云服务器ECS端口在安全组中开启&#xff0c;轻量应用服务器端口在防火墙中打开&#xff0c;新手站长以开通80端口为例来详细说下阿里云服务器端口开放图文教程&#xff0c;其他的端口如8080、3306、443、1433也是同样的方法进行开启端口&a…

双轮云台小车实现追踪彩色目标功能

1. 功能说明 在R216a样机上安装一个摄像头&#xff0c;本文示例将实现双轮小车通过二自由度云台自主寻找彩色目标的功能。 2. 结构说明 R216a样机主要是由一个 双轮小车 和一个 2自由度云台 组合而成。 3. 电子硬件 在这个示例中&#xff0c;我们采用了以下硬件&#xff0c;请大…

CRM系统软件不好用有哪些原因?如何选择?

CRM系统的实施也会出现无法落地使用的情况&#xff0c;让CRM系统软件名存实亡。这不仅仅只是个例&#xff0c;很多企业即使投入了很大成本&#xff0c;也不能让CRM系统真正用起来。CRM系统软件用不起来&#xff0c;可以排查这三个原因&#xff0c;教你解决&#xff01; 1.操作…