锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 网络与通信
  3. 【网络编程】——基于TCP协议实现回显服务器及客户端

【网络编程】——基于TCP协议实现回显服务器及客户端

0
  • 网络与通信
  • 发布于 2024-09-28
  • 0 次阅读
黄健
黄健

个人主页:兜里有颗棉花糖
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创
收录于专栏【网络编程】【Java系列】
本专栏旨在分享学习网络编程的一点学习心得,欢迎大家在评论区交流讨论💌


目录

  • 一、TCP实现回显服务器
  • 二、服务器端
  • 三、客户端
  • 四、运行结果


一、TCP实现回显服务器

TCP提供的API主要有两个类Socket(既会给服务器使用也会给客户端使用)和ServerSocket(一般为服务器使用)。TCP将数据分割成以字节为单位的小数据块进行传输(一个TCP数据报就是一个字节数组byte[])。

二、服务器端

在服务器端创建一个ServerSocket对象,并绑定一个端口号。

进入while循环:
注意这里和Udp实现回显服务器不同的是,Tcp进入循环之后并不是读取客户端请求,而是先处理客户端的连接(Tcp是一个有连接的协议(Udp是没有连接的协议),所以有连接的话会优先处理连接,连接可以理解为客户端和服务器彼此之间保留对方的信息)。一个服务器要应对很多客户端,在服务器内核中有很多客户端的连接,在应用程序层面我们需要对这些连接进行一一处理,这里服务器内核中的连接就像一个一个的待办事项一样,这些待办事项在队列这样的数据结构中,所以应用程序需要一一完成这样的任务(这个过程类似于生产者消费者模型)。
serverSocket.accept()方法可以将服务器内核中的连接获取到应用程序中

当程序启动之后就会立刻执行到accept方法,在调用serverSocket.accept()方法之后,如果此时没有客户端连接请求到达,该方法会一直阻塞,直到有客户端与服务器成功建立连接才会继续执行。
现在来解释这里的返回值问题,serverSocket.accept()方法会返回一个Socket对象:我们已经直到accept方法会把服务器内核已经建立好的连接拿到应用程序中,但是accpet方法的返回值并非是一个Connection这样的对象,而是Socket这样的对象。
这里返回的Socket对象相当于一个耳麦,既可以发出自己的声音也可以听到对方的声音(我们不需要管对方是谁,我们只需要对着这个耳麦说话就行)。然后我们通过Socket对象与对方进行网络通信
Socket和ServerSocket:
ServerSocket类用于在服务器端创建一个服务器套接字,它监听指定的端口,等待客户端的连接请求:通过调用ServerSocket的accept()方法,服务器监听指定端口,直到有客户端发起连接请求,accept()方法才返回一个表示客户端连接的Socket对象。通过这个Socket对象,可以进行与客户端的通信。
Socket类用于创建一个客户端套接字,它是客户端与服务器进行通信的终点:通过调用Socket的构造方法,指定服务器的主机名和端口号,可以与服务器建立连接。
总的来说:ServerSocket用于监听端口,接受客户端的连接请求并返回一个Socket对象,而Socket用于与服务器建立连接,并进行数据的读写操作。通过这两个类的配合,实现了TCP协议下的客户端与服务器之间的通信。

服务器端代码如下

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServer {

    private ServerSocket serverSocket = null;
    private ExecutorService service = Executors.newCachedThreadPool();
    // 绑定端口号
    public  TcpEchoServer(int port) throws IOException {

        serverSocket = new ServerSocket(port);
    }

    // 启动服务器
    public void start() throws IOException {

        System.out.println("服务器启动!!!");
        while(true) {

            // 注意这里和Udp不同的是,Tcp进入循环之后并不是读取客户端请求,而是先处理客户端的连接
            // Tcp是一个有连接的协议(Udp是没有连接的协议),所以有连接的话会优先处理连接
            // 连接可以理解为客户端和服务器彼此之间保留对方的信息
            // 一个服务器要应对很多客户端,在服务器内核中有很多客户端的连接,在应用程序层面我们需要对这些连接进行一一处理
            // 这里服务器内核中的连接就像一个一个的待办事项一样,这些待办事项在队列这样的数据结构中
            // 所以应用程序需要一一完成这样的任务
            Socket clientSocket = serverSocket.accept();
//            Thread t = new Thread(() -> {

//                processConnection(clientSocket);
//            });
//            t.start();
            service.submit(new Runnable() {

                @Override
                public void run() {

                    processConnection(clientSocket);
                }
            });
        }
    }

    // 通过这个方法来处理连接的逻辑
    private void processConnection(Socket clientSocket) {

        System.out.printf("[%s:%d] 客户端上线啦!!!\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
        // 接下来读取请求,根据请求计算响应,最后再返回响应
        // Socket对象内部包含了两个字节流对象,我们需要先获取到这个字节流对象,然后再完成后续的读写操作
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {

            // 一次连接中可以涉及到多次请求和响应
            while( true ) {

                // 第一步:读取请求并进行解析
                // 这里为了读取方便,我们直接使用Scanner
                Scanner scanner = new Scanner(inputStream);
                if(!scanner.hasNext()) {

                    // 读取完毕客户端下线

                    System.out.printf("[%s:%d] 客户端下线!!!\n]",clientSocket.getInetAddress().toString(),clientSocket.getPort());
                    break;
                }
                // 这里我们约定客户端输入来的请求是文本数据,同时以空白符作为分割
                String request = scanner.next();

                // 第二步:根据请求计算响应
                String response = process(request);

                // 第三步:把响应写回给客户端,把OutputStream使用PrinterWriter进行包装,方法进行数据的传输
                PrintWriter writer = new PrintWriter(outputStream);
                writer.println(response);

                // 刷新缓冲区
                writer.flush();

                // 打印当前的请求详情
                System.out.printf("[%s:%d] req: %s, resp: %s\n",clientSocket.getInetAddress().toString(),
                                                                clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {

            e.printStackTrace();
        } finally {

            try {

                clientSocket.close();
            } catch (IOException e) {

                // 这里必须确保Socket能够被关闭
                e.printStackTrace();
            }
        }
    }

    private String process(String request) {

        return request;
    }

    public static void main(String[] args) throws IOException {

        TcpEchoServer server = new TcpEchoServer(9090);
        server.start();
    }
}

三、客户端

关于回显服务器这里我们来看客户端的代码是如何进行编写的,主要有4个步骤,如下:

  • 第一步:从控制台上读取用户的输入。
  • 第二部:把输入的内容构造成请求,并将其发送给服务器。
  • 第三步:从服务器读取响应
  • 最后一步:把响应显示到控制台上。

客户端代码如下:

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {

    private Socket socket = null;

    // 要和服务器进行通信的话我们就需要先知道服务器的位置外哪里。
    public TcpEchoClient(String serverIp,int serverPort) throws IOException {

        socket = new Socket(serverIp,serverPort);
    }

    public void start() {

        System.out.println("客户端启动!!!");
        Scanner scannerConsole = new Scanner(System.in);
        try(InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream()) {

            while(true) {

                // 从控制台输入一个字符串
                System.out.print("-> ");
                String request = scannerConsole.next();
                // 把请求发送给服务器
                PrintWriter printWriter = new PrintWriter(outputStream);
                // 使用println加上换行,后续服务器读取请求的时候就可以使用scanner.next来获取了
                printWriter.println(request);
                // 调用flush确保数据发送出去了
                printWriter.flush();
                // 从服务器中读取响应
                Scanner scannerNetwort = new Scanner(inputStream);
                String response = scannerNetwort.next();
                // 把响应打印出来
                System.out.println(response);
            }
        } catch (IOException e) {

            e.printStackTrace();
        }

    }
    public static void main(String[] args) throws IOException {

        TcpEchoClient client = new TcpEchoClient("127.0.0.1",9090);
        client.start();
    }
}

四、运行结果

运行结果如下:


本文到这里就结束了,希望友友们可以支持一下一键三连哈。嗯,就到这里吧,再见啦!!!

原文链接: https://blog.csdn.net/m0_74352571/article/details/135209036

标签: #网络与通信 23 #知识库 257
相关文章

不懂组网方案、网络平面、网络架构?看这一篇就够了 2024-11-02 15:33

点击上方蓝色字体关注,知识分享 0 1 前言 大家好,云智能知识分享,不懂组网方案、网络平面、网络架构?看这一篇就够了,下面我们一起来看下有哪些知识点! 0 2 正文 组网方案 为了提升网络的安全性,使业务接口的流量负载均衡,NCE把网络划分为多个相互隔离的网络平面,分别为硬件管理网络、客户端/北向

光纤的跳线、尾纤区别在哪? 2024-11-02 15:33

跳线和尾纤是光纤通信系统中常见的两种连接组件,它们在结构、用途和应用场景上有所不同。 主要区别 | 特性 | 跳线 | 尾纤 | |———–|————————–|—————————| | 定义 | 一段带有两端连接器的光纤线缆,用于设备间连接 | 一段只有一端带有连接器的光纤线缆,另一端裸露光纤 |

如何确定光纤用几芯?用光纤与网线区别在哪里?

如何确定光纤用几芯?用光纤与网线区别在哪里? 2024-10-26 08:43

不少朋友在做光纤项目时,都有一个疑问,光纤需要用几芯的? 本期我们一起来总结下。 01 光纤用几芯? 光纤芯数,主要和光纤连接的设备接口和设备的通信方式有关。一般来说,光纤中光芯的数量,为设备接口总数乘以2后,再加上10%~20%的备用数量,而如果设备的通信方式有设备多路复用,就能减少芯数。 按照I

智能化弱电工程界面划分表,17个系统,很详细

智能化弱电工程界面划分表,17个系统,很详细 2024-10-21 09:07

弱电系统有哪些 ,如何进行划分界面呢?这个经常有项目经理不是很清楚,常见的弱电系统有17个,我们本期一起来看下,如何对弱电系统划分施工。 弱电智能化工程界面划分表 比较详细,包括弱电大部分的系统,适用于弱电大部分项目。 此图下载版本已上传知识星球,星球资料不断更新,若要下载相关弱电精品资料的,可以扫

这是一款网络工程师电脑必装的软件:SecureCRT,从零安装到精通,看本文足够了! 2024-09-30 16:47

你好,这里是网络技术联盟站,我是瑞哥。 SecureCRT 是一款广泛使用的终端仿真程序,由 VanDyke Software 公司开发。它旨在为网络管理员、工程师和开发人员提供安全、可靠的终端仿真和文件传输功能。SecureCRT 支持多种协议,包括 SSH、Telnet、Serial、RLogi

【机房-网络设备运维常识总结(2024-8-2更新)】 2024-09-30 16:47

机房-网络设备运维常识总结 一、服务器构造 二、服务器组件拆装 三、网络设备及耗材介绍 四、使用Xshell进行交换机管理 五、通过服务器进入BIOS进行基础配置 一、服务器构造 1、服务器高度:1U=4.445cm,常见服务器高度为1U、2U。 2、服务器前面板:指示灯(健康灯、UID灯)、电源按

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.