0


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

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

目录

一、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协议下的客户端与服务器之间的通信。**

服务器端代码如下

importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.io.PrintWriter;importjava.net.ServerSocket;importjava.net.Socket;importjava.util.Scanner;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;publicclassTcpEchoServer{privateServerSocket serverSocket =null;privateExecutorService service =Executors.newCachedThreadPool();// 绑定端口号publicTcpEchoServer(int port)throwsIOException{
        serverSocket =newServerSocket(port);}// 启动服务器publicvoidstart()throwsIOException{System.out.println("服务器启动!!!");while(true){// 注意这里和Udp不同的是,Tcp进入循环之后并不是读取客户端请求,而是先处理客户端的连接// Tcp是一个有连接的协议(Udp是没有连接的协议),所以有连接的话会优先处理连接// 连接可以理解为客户端和服务器彼此之间保留对方的信息// 一个服务器要应对很多客户端,在服务器内核中有很多客户端的连接,在应用程序层面我们需要对这些连接进行一一处理// 这里服务器内核中的连接就像一个一个的待办事项一样,这些待办事项在队列这样的数据结构中// 所以应用程序需要一一完成这样的任务Socket clientSocket = serverSocket.accept();//            Thread t = new Thread(() -> {//                processConnection(clientSocket);//            });//            t.start();
            service.submit(newRunnable(){@Overridepublicvoidrun(){processConnection(clientSocket);}});}}// 通过这个方法来处理连接的逻辑privatevoidprocessConnection(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){// 第一步:读取请求并进行解析// 这里为了读取方便,我们直接使用ScannerScanner scanner =newScanner(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 =newPrintWriter(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();}}}privateStringprocess(String request){return request;}publicstaticvoidmain(String[] args)throwsIOException{TcpEchoServer server =newTcpEchoServer(9090);
        server.start();}}

三、客户端

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

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

客户端代码如下:

importjava.io.*;importjava.net.Socket;importjava.util.Scanner;publicclassTcpEchoClient{privateSocket socket =null;// 要和服务器进行通信的话我们就需要先知道服务器的位置外哪里。publicTcpEchoClient(String serverIp,int serverPort)throwsIOException{
        socket =newSocket(serverIp,serverPort);}publicvoidstart(){System.out.println("客户端启动!!!");Scanner scannerConsole =newScanner(System.in);try(InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()){while(true){// 从控制台输入一个字符串System.out.print("-> ");String request = scannerConsole.next();// 把请求发送给服务器PrintWriter printWriter =newPrintWriter(outputStream);// 使用println加上换行,后续服务器读取请求的时候就可以使用scanner.next来获取了
                printWriter.println(request);// 调用flush确保数据发送出去了
                printWriter.flush();// 从服务器中读取响应Scanner scannerNetwort =newScanner(inputStream);String response = scannerNetwort.next();// 把响应打印出来System.out.println(response);}}catch(IOException e){
            e.printStackTrace();}}publicstaticvoidmain(String[] args)throwsIOException{TcpEchoClient client =newTcpEchoClient("127.0.0.1",9090);
        client.start();}}

四、运行结果

运行结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

标签: 网络 tcp/ip 服务器

本文转载自: https://blog.csdn.net/m0_74352571/article/details/135209036
版权归原作者 兜里有颗棉花糖 所有, 如有侵权,请联系我们删除。

“【网络编程】——基于TCP协议实现回显服务器及客户端”的评论:

还没有评论