为什么有些网站更新的信息看不到,网站之间如何做视频交换,北京南站,百度推广官网登录回显服务器表示客户端传来的请求是什么#xff0c;服务器就回应什么#xff0c;客户端不用对传来的数据进行处理#xff0c;主要是为了熟悉TCP协议提供的API的使用
对于代码的解释全作为注释写在了代码上#xff0c;推荐复制到编程软件中查看
UDP协议实现回显服务器可以看… 回显服务器表示客户端传来的请求是什么服务器就回应什么客户端不用对传来的数据进行处理主要是为了熟悉TCP协议提供的API的使用
对于代码的解释全作为注释写在了代码上推荐复制到编程软件中查看
UDP协议实现回显服务器可以看UDP数据报网络编程实现简单的回显服务器客户端
其中涉及到的线程池的内容可以看通过标准库创建线程池
idea开启多个客户端的方法可以看idea如何开启多个客户端一个代码开启多个客户端运行
服务器代码
package TcpEcho;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** Created with IntelliJ IDEA.* Description:* User: wuyulin* Date: 2023-08-10* Time: 16:25*/
//TCP协议 回显服务器客户端传来的请求是什么服务器就回应什么
//TCP协议网络编程两个最主要的类是ServerSocket和Socket
public class TcpEchoServer {//线程池对象ExecutorService executorService null;//ServerSocket类内置了一个队列在内核中客户端和服务器尝试建立连接连接建立完了以后得到的连接对象就存入了队列中//客户端和服务器尝试建立连接进行一系列的数据交互称为“握手”这个过程建立完了以后连接就建立好了private ServerSocket serverSocketnull;//在构造方法中实例化serverSocket对象port参数表示在创建服务器时要指定服务器的ip地址TcpEchoServer(int port) throws IOException {serverSocketnew ServerSocket(port);executorServiceExecutors.newCachedThreadPool(); //实例化一个线程数目动态变化的线程池}public void start() throws IOException {//写日志方便观察当前运行状态System.out.println(服务器启动);//服务器需要不停的去接收客户端传来的请求并做出回应所以需要一个死循环while (true){//TCP是有连接的需要处理服务器与客户端之间的连接而UDP是无连接的不需要处理//处理服务器与客户端之间的连接//通过调用accept方法取出serverSocket对象内置的队列中的连接对象Socket对象//当队列中没有Socket连接对象时就会在accept方法这里进入阻塞等待直到取得连接对象为止Socket socketserverSocket.accept();//对获得的服务器与客户端之间的连接对象进行处理//采用当前的编写方式会发现当有多个客户端来连接服务器并发出请求时服务器不能同时处理//因为在handleConnection方法中会一直循环处理客户端发出的请求//而当前编写方式要等handleConnection方法执行完毕才能去取出下一个连接对象才能处理下一个客户端发出的请求// handleConnection(socket);//解决办法用主线程去调用accept方法取出连接对象每取出一个连接对象就创建一个线程去处理连接对象对应的客户端发出的请求//但下面这个创建线程来处理socket连接对象的代码也注释掉了这是因为要是有很多客户端来对服务器发出请求就会涉及到大量//线程的创建和销毁这是很消耗资源的所以应该采用线程池来处理socket连接对象
// Thread tnew Thread(()-{
// try {
// handleConnection(socket);
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// });
//
// t.start();//在该服务器类的成员属性中添加上线程池//将处理连接对象的任务通过submit添加到线程池的阻塞队列中(线程池中的线程会将添加到阻塞队列中的任务进行处理)executorService.submit(new Runnable() {Overridepublic void run() {try {handleConnection(socket);} catch (IOException e) {throw new RuntimeException(e);}}});}}//处理客户端和服务器之间的连接并且完成数据的接收处理回应public void handleConnection(Socket socket) throws IOException {System.out.printf(客户端上线 %s %d\n,socket.getInetAddress().toString(),socket.getPort());//由于TCP协议的网络编程进行数据传输的基本单位是字节所以需要inputstream和outputstream类型的对象来处理字节流的数据//socket网络连接对象可以直接实例化InputStream和OutputStream对象来对网络要传输的字节数据进行处理//采用try(){}的结构在中实例化inputStream和outputStream对象可以在{}中的程序执行结束了以后自动关闭这两个对象防止内存泄漏try(InputStream inputStreamsocket.getInputStream();OutputStream outputStreamsocket.getOutputStream()){//处理客户端传来的请求//客户端传来的请求可能不止一个所以需要一直死循环去一直读取客户端传来的请求while (true){//InputStream直接使用不是很方便包装一层Scanner使用Scanner scannernew Scanner(inputStream);//当没有读取到请求了客户端传来的请求读取完了就跳出循环结束方法去拿下一个网络连接对象进行处理//当客户端还没有传入请求时就会进入阻塞等待直到客户端传入请求或客户端下线才恢复if(!scanner.hasNext()){//只有当客户端下线才会执行这段代码System.out.printf(%s %d客户端下线,socket.getInetAddress().toString(),socket.getPort());break;}//客户端中还有请求读取客服端的请求到request字符串中//这里默认了客户端传来的请求是字符串按照字符串的形式来处理请求String requestscanner.next();//对客户端传来的请求进行处理并作出响应String responsehandle(request);//将响应传递给客户端//直接使用outputStream比较麻烦包装一层PrintWriter进行使用PrintWriter printWriternew PrintWriter(outputStream);//要调用println方法将回应传递给客户端才行因为println方法在传递了一个回应后会换行而在客户端中就刚好可以用next方法读取//next方法不会读取空白符而换行属于空白符printWriter.println(request);//由于IO操作很消耗资源所以在调用println方法向客户端发送数据时会先将数据放到一个内存缓冲区中等到有一定的内容再一起发送//所以为了保证回应被及时的发到客户端就要对内存缓冲区进行刷新printWriter.flush();//写日志方便观察当前运行状态System.out.printf([%s,%d] request:%s response:%s\n,socket.getInetAddress().toString(),socket.getPort(),request,response);}} catch (IOException e) {throw new RuntimeException(e);}finally { //Socket连接对象会被不停的从serverSocket对象中取出所以在使用完毕Socket连接对象以后应该调用close方法关闭否则会出现内存泄漏socket.close();}}//对客户端传来的请求进行处理public String handle(String request){return request;}public static void main(String[] args) throws IOException {TcpEchoServer tcpEchoServernew TcpEchoServer(1010);tcpEchoServer.start();}
}客户端代码
package TcpEcho;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Scanner;/*** Created with IntelliJ IDEA.* Description:* User: wuyulin* Date: 2023-08-10* Time: 19:26*/
//TCP回显客户端
public class TcpEchoClient {//客户端需要实例化一个连接对象Socket来实现客户端与服务器之间的数据交互Socket socketnull;//在实例化连接对象Socket时需要服务器的ip地址和端口号TcpEchoClient(String serverIp,int serverPort) throws IOException {socketnew Socket(serverIp,serverPort);}public void start(){//写日志方便观察当前运行状态System.out.println(客户端启动);//TCP协议进行网络编程传递数据的基本单位是字节所以需要用到InputStream和OutputStream的对象来进行数据的传输//通过连接对象即可实例化InputStream和OutputStream的对象try(InputStream inputStreamsocket.getInputStream();OutputStream outputStreamsocket.getOutputStream();){//客户端需要不停的读取客户输入的请求所以要用循环while (true){Scanner scannernew Scanner(System.in);//读取用户的请求System.out.println(-);String requestscanner.next();//将用户的请求发送给服务器//直接使用outputStream不方便包装一层PrintWriter使用PrintWriter printWriternew PrintWriter(outputStream);printWriter.println(request);//由于IO操作很消耗资源所以在调用println方法向客户端发送数据时会先将数据放到一个内存缓冲区中等到有一定的内容再一起发送//所以为了保证请求被及时的发到服务器就要对内存缓冲区进行刷新printWriter.flush();//接收服务器处理后的回应//直接使用inputStream不方便包装一层Scanner使用Scanner inputScannernew Scanner(inputStream);String responseinputScanner.next();//将回应打印到控制台System.out.println(response);}} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws IOException {TcpEchoClient tcpEchoClientnew TcpEchoClient(127.0.0.1,1010);tcpEchoClient.start();}
}