编写Java程序,实现一个简单的echo程序(网络编程TCP实践练习)

简介: 编写Java程序,实现一个简单的echo程序(网络编程TCP实践练习)

首先启动服务端,客户端通过TCP的三次握手与服务端建立连接;


然后,客户端发送一段字符串,服务端收到字符串后,原封不动的发回给客户端。


ECHO 程序是网络编程通信交互的一个经典案例,称为回应程序,即客户端输入哪些内容,服务端会在这些内容前加上“ECHO”并将信息发回给客户端。

45.png46.png


EchoServer.java

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class EchoServer {
  private ServerSocket server;
  public EchoServer() throws IOException {
    // 创建服务端套接字对象
    this.server = new ServerSocket(8888);
    System.out.println("服务器启动" + "在" + 8888 + "端口监听连接请求");
  }
  // 服务器主要的处理逻辑
  public void service() {
    // 是否关闭服务端连接
    boolean flag = true;
    while (flag) {
      Socket socket = null;
      try {
        // 获取连接的客户端套接字对象
        socket = server.accept();
        // 获取socket相关的输入流和输出流
        BufferedReader reader = getReader(socket);
        BufferedWriter writer = getWriter(socket);
        // 保存客户端发送的数据
        String data = null;
        // 读取客户端发送的数据
        while ((data = reader.readLine()) != null) {
          // 当获取的信息是“bye”时,关闭流
          if ("bye".equals(data)) {
            flag = false;
            if (reader != null) {
              reader.close();
            }
            if (writer != null) {
              writer.close();
            }
            break;
          } else {
            System.out.println("来自客户端的数据:" + data);
            // 回显给客户端的数据
            writer.write("echo:" + data);
            // 插入一个行分割符,readLine()方法用来判定字符串有没结束
            writer.newLine();
            // 刷新输出缓冲区
            writer.flush();
          }
        }
      } catch (IOException e) {
        // 设置结束循环
        flag = false;
      } finally {
        try {
          if (server != null && (!server.isClosed())) {
            server.close();
            System.out.println("服务端关闭");
          }
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
  // 获取socket相关的输入流对象
  private BufferedReader getReader(Socket socket) throws IOException {
    InputStream in = socket.getInputStream();
    return new BufferedReader(new InputStreamReader(in));
  }
  // 获取socket相关的输出流对象
  private BufferedWriter getWriter(Socket socket) throws IOException {
    OutputStream out = socket.getOutputStream();
    return new BufferedWriter(new OutputStreamWriter(out));
  }
  public static void main(String arg[]) throws IOException {
    new EchoServer().service();
  }
}


EchoClient.java


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class EchoClient {
  private Socket socket;
  public EchoClient() {
    try {
      // 创建客户端套接字对象
      this.socket = new Socket("127.0.0.1", 8888);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  public void talkToServer() {
    System.out.println("请输入要发送给服务端的数据:");
    BufferedReader localReader = null;
    String data = null;
    // 获取客户端套接字相关的输入流和输出流
    BufferedReader reader = getReader(socket);
    BufferedWriter writer = getWriter(socket);
    try {
      // 创建读取用户输入的读取流
      localReader = new BufferedReader(new InputStreamReader(System.in));
      while ((data = localReader.readLine()) != null) {
        // 如果客户端输入的数据是"bye",则关闭I/O流
        if ("bye".equals(data)) {
          System.out.println("客服端关闭!");
          if (reader != null) {
            reader.close();
          }
          if (writer != null) {
            writer.close();
          }
          break;
        } else {
          // readLine方法必须读取到行分割符才返回读取。所以传递给输入流的字符串必须包含行分割符
          System.out.println("客户端输出的数据--->\t" + data);
          writer.write(data);
          // 插入一个行分隔符,作为内容结束的标识
          writer.newLine();
          // 非常重要的是必须显式的将数据推送到服务器哪里去
          writer.flush();
          // 读取服务端返回的数据
          System.out.println("服务器响应的数据--->\t " + reader.readLine());
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      // 关闭客户端套接字连接
      try {
        if (socket != null) {
          socket.close();
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  // 获取客户端套接字相关的输出流
  private BufferedWriter getWriter(Socket socket) {
    try {
      OutputStream out = null;
      BufferedWriter writer = null;
      out = socket.getOutputStream();
      writer = new BufferedWriter(new OutputStreamWriter(out));
      return writer;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
  // 获取客户端套接字相关的输入流
  private BufferedReader getReader(Socket socket) {
    try {
      InputStream in = null;
      BufferedReader reader = null;
      in = socket.getInputStream();
      reader = new BufferedReader(new InputStreamReader(in));
      return reader;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }
  public static void main(String[] args) {
    new EchoClient().talkToServer();
  }
}
相关文章
|
6天前
|
监控 Java 开发者
深入理解 Java 网络编程和 NIO
【4月更文挑战第19天】Java网络编程基于Socket,但NIO(非阻塞I/O)提升了效率和性能。NIO特点是非阻塞模式、选择器机制和缓冲区,适合高并发场景。使用NIO涉及通道、选择器和事件处理,优点是高并发、资源利用率和可扩展性,但复杂度、错误处理和性能调优是挑战。开发者应根据需求选择是否使用NIO,并深入理解其原理。
|
8天前
|
网络协议 Java API
深度剖析:Java网络编程中的TCP/IP与HTTP协议实践
【4月更文挑战第17天】Java网络编程重在TCP/IP和HTTP协议的应用。TCP提供可靠数据传输,通过Socket和ServerSocket实现;HTTP用于Web服务,常借助HttpURLConnection或Apache HttpClient。两者结合,构成网络服务基础。Java有多种高级API和框架(如Netty、Spring Boot)简化开发,助力高效、高并发的网络通信。
|
10天前
|
JavaScript Java 测试技术
基于Java的网络游戏交易系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的网络游戏交易系统的设计与实现(源码+lw+部署文档+讲解等)
23 0
|
10天前
|
SQL 安全 Java
Java安全编程:防范网络攻击与漏洞
【4月更文挑战第15天】本文强调了Java安全编程的重要性,包括提高系统安全性、降低维护成本和提升用户体验。针对网络攻击和漏洞,提出了防范措施:使用PreparedStatement防SQL注入,过滤和转义用户输入抵御XSS攻击,添加令牌对抗CSRF,限制文件上传类型和大小以防止恶意文件,避免原生序列化并确保数据完整性。及时更新和修复漏洞是关键。程序员应遵循安全编程规范,保障系统安全。
|
13天前
|
JavaScript Java 测试技术
基于Java的网络游戏交易平台信息管理系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的网络游戏交易平台信息管理系统的设计与实现(源码+lw+部署文档+讲解等)
25 1
|
15天前
|
JavaScript Java 测试技术
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
30 0
基于Java的网络类课程思政学习系统的设计与实现(源码+lw+部署文档+讲解等)
|
27天前
|
JSON Java 网络安全
Java使用hutool工具类发送网络请求
Java使用hutool工具类发送网络请求
41 0
|
1天前
|
缓存 Java
【Java基础】简说多线程(上)
【Java基础】简说多线程(上)
5 0
|
1天前
|
并行计算 算法 安全
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
|
1天前
|
安全 Java 编译器
是时候来唠一唠synchronized关键字了,Java多线程的必问考点!
本文简要介绍了Java中的`synchronized`关键字,它是用于保证多线程环境下的同步,解决原子性、可见性和顺序性问题。从JDK1.6开始,synchronized进行了优化,性能得到提升,现在仍可在项目中使用。synchronized有三种用法:修饰实例方法、静态方法和代码块。文章还讨论了synchronized修饰代码块的锁对象、静态与非静态方法调用的互斥性,以及构造方法不能被同步修饰。此外,通过反汇编展示了`synchronized`在方法和代码块上的底层实现,涉及ObjectMonitor和monitorenter/monitorexit指令。
6 0

热门文章

最新文章