IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> TCP回显程序中的小细节 -> 正文阅读

[系统运维]TCP回显程序中的小细节


💤

💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨💨

💤


客户端代码

public class TcpEchoClient {
    private String serverIp;
    private int serverPort;
    private Socket socket = null;

    public TcpEchoClient(String serverIp, int serverPort) throws IOException {
        this.serverIp = serverIp;
        this.serverPort = serverPort;
        // 让socket创建的同时,就和服务器尝试建立了连接
        socket = new Socket(serverIp,serverPort);
    }

    public void start(){
        Scanner scanner = new Scanner(System.in);
        try(InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream()){
            while(true){
                // 1.从键盘上,读取用户的内容
                System.out.println("-> ");
                String request = scanner.nextLine();
                if ("goodbye".equals(request)){
                    break;
                }
                // 2.把这个读取的内容构成请求,发送给服务器
                PrintWriter printWriter = new PrintWriter(outputStream);

                printWriter.print(request);

                // 3.从服务器读取响应并解析
                Scanner response = new Scanner(inputStream);
                String responseStrings= response.next();
                // 4.把结果显示到界面上
                String log = String.format("request: %s; response: %s",request,responseStrings);
                System.out.println(log);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws IOException {
        TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",8080);
        tcpEchoClient.start();
    }
}

服务器代码

public class TcpEchoServer {
    private ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("Server start!");
        while(true){
            // UDP的服务器进入主循环,就直接尝试receiver读取请求了
            // 但是TCP是有连接的,先要做的是,建立好连接
            // 当服务器运行的时候,当前是否有客户端来建立连接,不确定
            // 如果客户端没有建立连接了,accept就会阻塞等待
            // TODO: 2021/10/26 如果有多个客户端对同一个服务器尝试建立连接会发送什么?
            // 如果有客户端建立连接了,此时accept就会返回一个socket对象
            // 进一步的服务器和客户端之间的交互,就交给client Socket
            Socket clientSocket = serverSocket.accept();
            processConnection(clientSocket);
        }
    }

    private void processConnection(Socket clientSocket) throws IOException {
        // 处理一个连接,在这个连接中可能会涉及客户端和服务器之间的多次交互
        String log = String.format("[%s:%d] 客户端上线!",clientSocket.getInetAddress().toString(),
                clientSocket.getPort());
        System.out.println(log);
        // 输入
        try(InputStream inputStream = clientSocket.getInputStream();
            // 输出
            OutputStream outputStream = clientSocket.getOutputStream()) {
            while (true) {
                // 1.读取请求并解析
                //      可以直接通过 inputStream 的read 把数据读到一个byte[]上,然后再转成一个String
                //      但是比较麻烦,还可以借助Scanner 来完成工作
                Scanner scanner = new Scanner(inputStream);
                if (!scanner.hasNext()){
                    log = String.format("[%s:%d] 客户端下线",clientSocket.getInetAddress().toString(),
                            clientSocket.getPort());
                    System.out.println(log);
                    break;
                }
                String request = scanner.next();
                System.out.println(request);
                // 2.根据请求计算响应
                String response = process(request);
                // 3.把响应写回给客户端
                PrintWriter writer = new PrintWriter(outputStream);
                writer.print(response);
                log = String.format("[%s:%d] req: %s; resp: %s",clientSocket.getInetAddress(),
                        clientSocket.getPort(),request,response);
                System.out.println(log);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 当前的clientSocket生命周期,不是跟随整个程序,而是和连接相关
            // 因此就需要每个连接结束,都要进行关闭
            // 否则随着连接的增多,这个socket文件就可能出现资源泄漏的情况
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer = new TcpEchoServer(8080);
        tcpEchoServer.start();
    }

当我把服务器和客户端启动之后

Server start!
[/127.0.0.1:61497] 客户端上线!

服务器和客户端显示正常运行

但客户端发送请求后:

客户端
-> 
AKA

服务器没有做出任何的响应,这时候说明代码中存在bug

猜测:

?1.客户端可能没有正确的发送数据

?2.服务器可能没有正确读取数据

回到代码上

我们发送请求使用的是:

printWriter.print(request);

收取请求使用的是:

String request = scanner.next();

?这里分析一些scanner.next()方法

? next()在读取到什么字符的时候才能返回?

? 空白字符 如 空格、制表符、换行符、翻页符

所以为了解决这个问题我们就需要才外加空白字符

方便起见,发送请求使用:

printWriter.println(request);

当修改完成后,再次运行

当我们在客户端进行输入的时候,发现服务器还是收不到客户端的请求

这又是哪里出了问题???

回顾我们学习File和IO的时候,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。

因此我们的请求是不是被放到了缓冲区?

为了验证一下

我们在发送请求的下面加上这一行代码,用来刷新缓冲区

printWriter.print(request);
printWriter.flush();

再次运行

客户端
-> 
AKA
request: AKA; response: AKA
服务器
Server start!
[/127.0.0.1:61835] 客户端上线!
AKA
[/127.0.0.1:61835] req: AKA; resp: AKA

正常运行

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-10-30 12:50:22  更:2021-10-30 12:50:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 22:22:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码