TCP回显程序中的小细节

发布时间:2022-07-01 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了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 如果有多个客户端对同一个服务器尝试建立连接会发送什么F1f;
            // 如果有客户端建立连接了,此时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

正常运行

脚本宝典总结

以上是脚本宝典为你收集整理的TCP回显程序中的小细节全部内容,希望文章能够帮你解决TCP回显程序中的小细节所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。