> 文章列表 > TCP版本的 echo server 和 echo client

TCP版本的 echo server 和 echo client

TCP版本的 echo server 和 echo client

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • Tcp的api展示
  • 服务端
  • 客户端
  • 存在的问题
  • 解决问题
  • 服务端和客户端的大致流程

前言

上一篇文章我们介绍了UCP的客户端与服务器的一个简单实例,这篇我们简单的来介绍TCP版本的server和client的一个简单交互


Tcp的api展示

TCP版本的 echo server 和 echo client
TCP版本的 echo server 和 echo client

服务端

服务端的要做的流程
1.读取请求
2.根据请求计算响应
3.把响应写回给客户端

下面是完整代码

public class TpcEchoServer {//serverSocket就是外场拉课的小哥//clientSocket就是内场服务的小姐姐//serverSocket只有一个,clientSocket会给每个客户分配一个private ServerSocket serverSocket = null;public TpcEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}//启动过程public void start() throws IOException {System.out.println("服务器启动");ExecutorService executorService = Executors.newCachedThreadPool();//因为我们服务器要反复读取一个服务,所以我们要使用循环while (true) {Socket clientSocket = serverSocket.accept();processConnection(clientSocket);private void processConnection(Socket clientSocket) throws IOException {System.out.printf("[%s:%d] 客户端上线!\\n", clientSocket.getInetAddress().toString(),clientSocket.getPort());//try()这种写法种,允许写多个流对象.使用;来分割try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {//我们使用prinwriter把字节流包装秤字符流Scanner scanner = new Scanner(inputStream);PrintWriter printWriter = new PrintWriter(outputStream);while (true) {//1.读取请求if (!scanner.hasNext()) {//读到流的结尾了.System.out.printf("[%s:%d] 客户端下线!\\n", clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}//直接使用scanner读取一段字符串String request = scanner.next();//2.根据请求计算响应String response = process(request);//3.把响应写回给客户端printWriter.println(response);printWriter.flush();System.out.printf("[%s:%d] req: %s; resp : %s\\n", clientSocket.getInetAddress().toString(), clientSocket.getPort(), request, response);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {TpcEchoServer tcpEchoServer = new TpcEchoServer(9090);tcpEchoServer.start();}
}

我针对几个方法具体解释一下.

  private ServerSocket serverSocket = null;Socket clientSocket = serverSocket.accept();

TCP版本的 echo server 和 echo client
处理代码代码的解释:
TCP版本的 echo server 和 echo client

客户端

客户端的一个流程
1.从键盘上读取用户输入内容
2.讲读取的内容放给服务器
3.从服务器读取响应内容
4.把响应内容显示在控制台上

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;public class TcpEchoClient {private Socket socket = null;public TcpEchoClient(String serverIp, int port) throws IOException {//这个操作相当于让客户端和服务器建立tcp连接.//这里连接上了,socket就会返回socket = new Socket(serverIp, port);}//开始启动客户端public void start() {Scanner scanner = new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()){ PrintWriter printWriter = new PrintWriter(outputStream);Scanner scannerFromSocket = new Scanner(inputStream);while (true){//1.从键盘上读取用户输入内容System.out.println("->");String request= scanner.next();//2.讲读取的内容放给服务器printWriter.println(request);printWriter.flush();//3.从服务器读取响应内容String response=scannerFromSocket.next();//4.把响应内容显示在控制台上System.out.printf("req: %s; resp: %s\\n", request, response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TcpEchoClient tcpEchoClient=new TcpEchoClient("127.0.0.1",9090);tcpEchoClient.start();}
}

存在的问题

这里其实存在一个问题,就是当我们多个客户端去访问服务器的时候,服务端要处理完第一个客户端,在处理第二个客户端,具体看下图.
TCP版本的 echo server 和 echo client

解决问题

先来看看我们针对服务端的处理客户端的请求代码

  public void start() throws IOException {System.out.println("服务器启动");ExecutorService executorService = Executors.newCachedThreadPool();//因为我们服务器要反复读取一个服务,所以我们要使用循环while (true) {Socket clientSocket = serverSocket.accept();processConnection(clientSocket);}}

改造后的代码
TCP版本的 echo server 和 echo client

  public void start() throws IOException {System.out.println("服务器启动");ExecutorService executorService = Executors.newCachedThreadPool();//因为我们服务器要反复读取一个服务,所以我们要使用循环while (true) {Socket clientSocket = serverSocket.accept();Thread t = new Thread(() -> {try {processConnection(clientSocket);} catch (IOException e) {e.printStackTrace();}});}}

服务端和客户端的大致流程

TCP版本的 echo server 和 echo client