当前位置: 首页 > news >正文

个人网站备案备注范文wordpress自动添加关键字

个人网站备案备注范文,wordpress自动添加关键字,贸易网站怎么做,软件外包价格一般多少文章目录 4.TCP流套接字编程4.1ServerSocket API4.2Socket API4.3TCP中的长短连接4.4示例一#xff1a;一发一收#xff08;长连接#xff09;4.4.1TCP服务端4.4.2TCP客户端 4.5示例二#xff1a;请求响应#xff08;短连接#xff09;4.5.1TCP服务端4.5.2TCP客户端 4.6再… 文章目录 4.TCP流套接字编程4.1ServerSocket API4.2Socket API4.3TCP中的长短连接4.4示例一一发一收长连接4.4.1TCP服务端4.4.2TCP客户端 4.5示例二请求响应短连接4.5.1TCP服务端4.5.2TCP客户端 4.6再谈协议4.6.1回顾并理解为什么需要协议4.6.2封装/分用 vs 序列化/反序列化4.6.3如何设计协议 4.7示例三多线程自定义协议4.7.1本示例中的自定义协议4.7.2执行流程(xml json protobuffer)4.7.3请求类4.7.4响应类4.7.5TCP服务端4.7.6TCP客户端 4.8长连接 vs 短连接4.9UDP vs TCP 大家好我是晓星航。今天为大家带来的是 网络编程套接字(下) 相关的讲解 4.TCP流套接字编程 有连接(打电话) 可靠传输(有已读功能(例如抖音消息已读不回QAQ)) 面向字节流(数据传输就和文件读写IO 类似流式的) 全双工(一个通信通道可以双向传输。 既可以发送又可以接收) - 一根网线里面其实有 8 根线 和刚才UDP类似. 实现一个简单的英译汉的功能 4.1ServerSocket API ServerSocket 是创建TCP服务端Socket的API。 ServerSocket 构造方法 ServerSocket 方法 4.2Socket API Socket 是客户端Socket或服务端中接收到客户端建立连接accept方法的请求后返回的服务端 Socket。 不管是客户端还是服务端Socket都是双方建立连接以后保存的对端信息及用来与对方收发数据的。 Socket 构造方法 Socket 方法 服务器和客户端的 Socket 不是一个Socket可以把他们理解成两部正在通信的电话。 4.3TCP中的长短连接 TCP发送数据时需要先建立连接什么时候关闭连接就决定是短连接还是长连接 短连接每次接收到数据并返回响应后都关闭连接即是短连接。也就是说短连接只能一次收发数据。 长连接不关闭连接一直保持连接状态双方不停的收发数据即是长连接。也就是说长连接可以多次收发数据。 对比以上长短连接两者区别如下 建立连接、关闭连接的耗时短连接每次请求、响应都需要建立连接关闭连接而长连接只需要 第一次建立连接之后的请求、响应都可以直接传输。相对来说建立连接关闭连接也是要耗时 的长连接效率更高。主动发送请求不同短连接一般是客户端主动向服务端发送请求而长连接可以是客户端主动发送 请求也可以是服务端主动发。两者的使用场景有不同短连接适用于客户端请求频率不高的场景如浏览网页等。长连接适用于 客户端与服务端通信频繁的场景如聊天室实时游戏等。 扩展了解 基于BIO同步阻塞IO的长连接会一直占用系统资源。对于并发要求很高的服务端系统来说这样的 消耗是不能承受的。 由于每个连接都需要不停的阻塞等待接收数据所以每个连接都会在一个线程中运行。 一次阻塞等待对应着一次请求、响应不停处理也就是长连接的特性一直不关闭连接不停的 处理请求。 实际应用时服务端一般是基于NIO即同步非阻塞IO来实现长连接性能可以极大的提升。 4.4示例一一发一收长连接 以下为一个客户端一次数据发送和服务端多次数据接收一次发送一次接收可以接收多次即只 有客户端请求但没有服务端响应的示例 4.4.1TCP服务端 package network;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;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(启动服务器);//此处使用 CacheThreadPool使用 FixedThreadPool 不太合适 (线程数不太应该是有固定的......)ExecutorService threadPool Executors.newCachedThreadPool();while (true) {//使用这个 clientSocket 和具体的客户端进行交流Socket clientSocket serverSocket.accept();//此处使用多线程来处理。 // Thread t new Thread(()-{ // processConnection(clientSocket); // }); // t.start();//使用线程池threadPool.submit(()-{processConnection(clientSocket); });}}//使用这个方法来处理一个连接//这一个连接对应到一个客户端但是这里可能会涉及到多次交互private void processConnection(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) {//1.读取请求Scanner scanner new Scanner(inputStream);if (!scanner.hasNext()) {//没有下个数据说明读完了。(客户端关闭了连接)System.out.printf([%s:%d] 客户端下线\n,clientSocket.getInetAddress().toString(),clientSocket.getPort());break;}//注意 此处使用 next 是一直读取到换行符/空格/其他空白符结束但是最终返回结果里不包含上述 空白符。String request scanner.next();//2.根据请求构造响应String response process(request);//3.返回响应结果// OutputStream 没有 write String 这样的功能 可以把 String 里的字节数组拿出来进行写入// 也可以用字符流来转换一下。PrintWriter printWriter new PrintWriter(outputStream);//此处使用 println 来写入让结果带有一个 \n 换行方便对端来接收解析printWriter.println(response);//flush 用来刷新缓冲区保证当前写入的数据确实是发送出去了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 {//更合适的做法是把 close 放到 finally 里面保证一定能够执行到try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}public String process(String request) {return request;}public static void main(String[] args) throws IOException {TCPEchoServer server new TCPEchoServer(9090);server.start();} }运行后服务端就启动了控制台输出如下 可以看出此时代码是阻塞等待在 server.accept() 代码行直到有新的客户端申请建立连接。 在我们客户端启动后服务器这里显示我们客户端上线了。 在客户端输入 hello 之后服务器直接返回响应结果回去。 在我们客户端输入 exit 之后我们的服务端显示客户端下线了。 代码解析 效果是 “接收连接”前提是得有客户端来建立连接 客户端在构造 Socket 对象的时候就会指定服务器的 IP 和 端口 如果没有客户端来连接此时 accept 就会阻塞等待 这个代码中使用到一个 clientSocket.此时任意一个客户端连上来都会返回/创建一个 Socket 对象。(Socket 就是文件)每次创建一个 clientSocket 对象就要占用一个文件描述符表的位置。 因此在使用完毕之后就需要进行释放。 当前启动服务器后先启动客户端1可以看到正常的上线提示。再启动客户端2此时发现没有任何提示了。 客户端1 进行发送消息都ok。 客户端2 发送消息没有任何提示。 解决方法1 当 客户端1 退出之后。 此时客户端2 就一切正常了 解决方法2 此时我们改进一下代码加入线程池 可以看到在我们修改了服务器中的循环为线程池后此时我们的服务器就可以检测到多个客户端的上线了。 注意这里虽然使用了线程池了但是还不够我们服务器如果此时有成千上万个客户端那么就是成千上万个线程。这个事情对于我们机器来说就是一个很大的负担 为了解决这个问题我们可以进行 IO多路复用 IO多路转接 。 所谓的 IO多路复用 就是充分利用等待时间做别的事情。给线程安排个集合这个集合就放了一堆连接。这个线程主要负责监听这个集合哪个连接有数据来了线程就来处理哪个连接。(API 中 提供了一组 NIO 这样的类封装了上述多路复用的 API select,poll,epoll) eg 一个快递员要取三个餐A顾客想吃 热干面B顾客想吃 肉夹馍C顾客想吃 猪脚饭。 如果是单线程完成的话快递员就要先取热干面再取肉夹馍最后取猪脚饭 才能进行送单。 如果是多线程的话快递员召唤分身分别去取热干面、肉夹馍、和猪脚饭然后汇合一起送单。(很明显效率要更高) 但是我们这里真实的做法是利用等待时间来取餐我们先去三个地方进行点餐然后再去首先做好的餐品处取餐然后再去第二个地方取餐最后去第三个地方取餐这个做法就是我们的 IO多路复用 4.4.2TCP客户端 package network;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 serverPort) throws IOException {//Socket 构造方法能够识别 点分十进制格式的 IP 地址比 DatagramPacket 更方便//new 这个对象的同时就会进行socket new Socket(serverIP,serverPort);}public void start() {System.out.println(客户端启动);Scanner scanner new Scanner(System.in);try (InputStream inputStream socket.getInputStream();OutputStream outputStream socket.getOutputStream()){while (true) {//1.先从键盘上读取用户输入的内容System.out.print( );String request scanner.next();if (request.equals(exit)) {System.out.println(goodbye);break;}//2.把读取到的内容构造成请求发送给服务器PrintWriter printWriter new PrintWriter(outputStream);printWriter.println(request);//此处加上 flush 保证数据确实发送出去了printWriter.flush();//3.读取服务区的响应Scanner respScanner new Scanner(inputStream);String response respScanner.next();//4.把响应内容显示到界面上System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {TCPEchoClient client new TCPEchoClient(127.0.0.1,9090);client.start();} }上图表示我们服务器成功启动啦 在客户端输入 hello 后我们的客户端立即就返回了一个 hello 在我们客户端输入 exit 之后我们的客户端就退出了程序。 代码解析 这个对象构造过程就会触发 TCP 建立连接的过程。(打电话开始拨号了) 如果客户端没这个代码服务器就会在 accept 这里阻塞无法产生出 clientSocket 了。 4.5示例二请求响应短连接 示例一只是客户端请求和服务端接收并没有包含服务端的返回响应。以下是对应请求和响应的改造 构造一个展示服务端本地某个目录BASE_PATH的下一级子文件列表的服务 1客户端先接收键盘输入表示要展示的相对路径相对BASE_PATH的路径 2发送请求使用客户端Socket的输出流发送TCP报文。即输入的相对路径。 3服务端接收并处理请求使用服务端Socket的输入流来接收请求报文根据请求的路径列出下 一级子文件及子文件夹。 4服务端返回响应使用服务端Socket的输出流来发送响应报文。即遍历子文件和子文件夹每个 文件名一行返回给客户端。 5客户端接收响应使用客户端Socket的输入流来接收响应报文。简单的打印输出所有的响应内 容即文件列表。 4.5.1TCP服务端 package org.example.tcp.demo2; import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class TcpServer {//服务器socket要绑定固定的端口private static final int PORT 8888;//本地文件目录要展示的根路径private static final String BASE_PATH E:/TMP;public static void main(String[] args) throws IOException {// 1.创建一个服务端ServerSocket用于收发TCP报文ServerSocket server new ServerSocket(PORT);// 不停的等待客户端连接while(true) {System.out.println(------------------------------------------------ ---);System.out.println(等待客户端建立TCP连接...);// 2.等待客户端连接注意该方法为阻塞方法Socket socket server.accept();System.out.printf(客户端IP%s%n, socket.getInetAddress().getHostAddress());System.out.printf(客户端端口号%s%n, socket.getPort());// 5.接收客户端的数据需要从客户端Socket中的输入流获取InputStream is socket.getInputStream();// 为了方便获取字符串内容可以将以上字节流包装为字符流BufferedReader br new BufferedReader(new InputStreamReader(is, UTF-8));// 客户端请求只发送一行数据我们也只需要读取一行String request br.readLine();// 6.根据请求处理业务本地目录根路径请求路径作为要展示的目录列出下一级子文 件//请求的文件列表目录System.out.printf(客户端请求的文件列表路径为%s%n, BASE_PATH request);File dir new File(BASE_PATH request);//获取下一级子文件子文件夹File[] children dir.listFiles();// 7.返回响应给客户端通过客户端socket中的输出流发送响应数据OutputStream os socket.getOutputStream();// 为了方便输出字符串作为发送的内容可以将以上字节流包装为字符流PrintWriter pw new PrintWriter(new OutputStreamWriter(os, UTF8));// 7-1.返回的响应内容每个文件及目录名称为一行if(children ! null){for (File child : children) {pw.println(child.getName());}}// 7-2.有缓冲区的IO操作真正传输数据需要刷新缓冲区pw.flush();// 7-3.双方关闭连接服务端是关闭客户端socket连接socket.close();}} }以上服务端运行结果和示例一是一样的 --------------------------------------------------- 等待客户端建立TCP连接...4.5.2TCP客户端 package org.example.tcp.demo2; import java.io.*; import java.net.Socket; import java.util.Scanner; public class TcpClient {//服务端IP或域名private static final String SERVER_HOST localhost;//服务端Socket进程的端口号private static final int SERVER_PORT 8888;public static void main(String[] args) throws IOException {// 准备要发送的数据这里调整为键盘输入作为发送的内容Scanner scanner new Scanner(System.in);while(true) {System.out.println(------------------------------------------------ ---);System.out.println(请输入要展示的目录);// 每输入新行回车就作为发送的TCP请求报文String request scanner.nextLine();// 3.创建一个客户端流套接字Socket并与对应IP的主机上对应端口的进程建立连接Socket socket new Socket(SERVER_HOST, SERVER_PORT);// 4.发送TCP数据是通过socket中的输出流进行发送OutputStream os socket.getOutputStream();// 为了方便输出字符串作为发送的内容可以将以上字节流包装为字符流PrintWriter pw new PrintWriter(new OutputStreamWriter(os, UTF8));// 4-1.发送数据pw.println(request);// 4-2.有缓冲区的IO操作真正传输数据需要刷新缓冲区pw.flush();// 8.接收返回的响应数据通过socket中的输入流获取System.out.println(接收到服务端响应);InputStream is socket.getInputStream();// 为了方便获取字符串内容可以将以上字节流包装为字符流BufferedReader br new BufferedReader(new InputStreamReader(is, UTF-8));String line;// 一直读取到流结束TCP是基于流的数据传输一定要服务端关闭Socket输出流才表示客 户端接收的IO输入流结束while ((line br.readLine()) ! null) {System.out.println(line);}// 9.双方关闭连接客户端关闭socket连接socket.close();}} }客户端启动后会等待输入要展示的路径 --------------------------------------------------- 请输入要展示的目录在输入想查看的目录路径后会接收并打印服务端响应的文件列表数据 --------------------------------------------------- 请输入要展示的目录 / 接收到服务端响应 1 2 60441b1b8a74be3695ccc0d970693815 8f25103aa249707ee4ab17635142cd0e --------------------------------------------------- 请输入要展示的目录此时服务端也会打印接收到的客户端请求数据 --------------------------------------------------- 等待客户端建立TCP连接... 客户端IP127.0.0.1 客户端端口号52493 客户端请求的文件列表路径为E:/TMP/ --------------------------------------------------- 等待客户端建立TCP连接...目前TCP客户端和服务端实现的功能和UDP差不多但都存在几个问题 对于服务端来说处理一次请求并返回响应后才能再次处理下一次请求和响应效率是比较低 的。这个问题比较好解决可以使用多线程每次的请求与响应都在线程中处理。这样多个客户端 请求的话可以在多个线程中并发并行的执行。服务端解析请求是只读取了一行而客户端解析响应是一直读取到流结束。可以想想为什么解 析请求时没有读取到流结束 目前的业务双方都已约定好业务是展示目录下的文件列表且都只需要一种数据请求传输的数 据代表要展示的目录响应传输的数据代表文件列表每一行为一个文件名。 如要提供更多的业务如文件重命名文件删除等操作时就不能了。此时就需要提供更多的字段 来标识。一般我们需要设计更强大的协议。 4.6再谈协议 4.6.1回顾并理解为什么需要协议 以上我们实现的UDP和TCP数据传输除了UDP和TCP协议外程序还存在应用层自定义协议可以想 想分别都是什么样的协议格式。 对于客户端及服务端应用程序来说请求和响应需要约定一致的数据格式 客户端发送请求和服务端解析请求要使用相同的数据格式。服务端返回响应和客户端解析响应也要使用相同的数据格式。请求格式和响应格式可以相同也可以不同。约定相同的数据格式主要目的是为了让接收端在解析的时候明确如何解析数据中的各个字段。可以使用知名协议广泛使用的协议格式如果想自己约定数据格式就属于自定义协议。 4.6.2封装/分用 vs 序列化/反序列化 一般来说在网络数据传输中发送端应用程序发送数据时的数据转换如java一般就是将对象转换 为某种协议格式即对发送数据时的数据包装动作来说 如果是使用知名协议这个动作也称为封装如果是使用小众协议包括自定义协议这个动作也称为序列化一般是将程序中的对象转换为 特定的数据格式。 接收端应用程序接收数据时的数据转换即对接收数据时的数据解析动作来说 如果是使用知名协议这个动作也称为分用如果是使用小众协议包括自定义协议这个动作也称为反序列化一般是基于接收数据特定的 格式转换为程序中的对象 4.6.3如何设计协议 对于协议来说重点需要约定好如何解析一般是根据字段的特点来设计协议 对于定长的字段: 可以基于长度约定如int字段约定好4个字节即可 对于不定长的字段 可以约定字段之间的间隔符或最后一个字段的结束符如换行符间隔\3符号结束等等除了该字段“数据”本身再加一个长度字段用来标识该“数据”长度即总共使用两个字段 “数据”字段本身不定长需要通过“长度”字段来解析“长度”字段标识该“数据”的长度即用于辅助解析“数据”字段 4.7示例三多线程自定义协议 以下我们将示例二的业务做以下扩展 提供多种操作展示目录下文件列表文件重命名删除文件上传文件下载文件在不同的操作中需要抽象出请求和响应的字段也即是说要约定客户端服务端统一的请求协 议同时也要约定服务端与客户端统一的响应协议 4.7.1本示例中的自定义协议 以下为我们TCP请求数据的协议格式这里简单起见约定为换行符及结束符 请求类型 操作的文件或目录路径 数据 \3 说明如下 以上总共包含3个字段前2个字段需要按换行符读取最后一个字段需要按结束符读取请求类型标识是什么操作展示目录下文件列表文件重命名删除文件上传文件下载文件重命名、上传文件操作需要“数据”字段其他操作可以置为空字符串“数据”字段为最后一个字段使用\3结束符这样在数据本身有换行符也能正确处理 以下为响应数据的协议格式 状态码标识是否操作成功 数据展示列表时返回目录下的文件列表或下载文件的数据\3 以下为展示文件列表操作的自定义协议请求、响应格式 以下操作将展示服务端根目录下的子文件及子文件夹 请求数据格式如下 1 / \3响应数据格式如下 200 \1 \2 \3 \1.txt \2.txt\3以下为上传文件操作的自定义协议请求、响应格式 需要先在客户端指定上传的服务端目录及客户端要上传的文件路径以下操作将会把客户端 Main.java 文件内容上传到服务端根目录 E:/TMP 下的 /1 目录下 请求数据格式如下 4 /1 package org.example; public class Main { ……略 }\3响应数据格式如下 200 \34.7.2执行流程(xml json protobuffer) 约定好请求和响应的数据格式也就是应用层协议大家按照约定好的格式来发送和接收以下为执行流程 xml json 上述 xml 和 json 都是按照文本的方式来组织的。 优点可读性好用户不需要借助其他的工具肉眼就能看懂数据的含义 缺点效率不高尤其是占用较多的网络带宽(xml 中要额外传很多的标签 json 中要额外传很多的 key 对于服务器来说最贵的硬件资源不是cpu更不是内存而是网络带宽!!!) protobuffer (谷歌) 二进制表示数据的方式针对上述的数据信息通过二进制的方式进行压缩表示了。 优点占用空间小传输的带宽也就降低了 缺点肉眼观察不了直接用记事本打开是一串011001类似的乱码 4.7.3请求类 先按照约定的请求协议封装请求类 每个字段为一个属性操作类型操作路径数据完成服务端解析请求封装按约定的方式读先按行读取前2个字段再按结束符读第3个字段完成客户端发送请求封装按约定的方式写前2个字段按行输出第3个字段以\3结束 package org.example.tcp.demo3; import java.io.*; import java.util.ArrayList; import java.util.List; public class Request {//操作类型1展示目录文件列表2文件重命名3删除文件4上传文件5下载 文件private Integer type;//操作的目录路径private String url;//数据private String data;//服务端解析请求时根据约定好的格式来解析public static Request serverParse(InputStream is) throws IOException {BufferedReader br new BufferedReader(new InputStreamReader(is, UTF8));Request request new Request();//前2行分别为操作类型和操作路径request.type Integer.parseInt(br.readLine());request.url br.readLine();//使用list保存字符ListCharacter list new ArrayList();//数据循环读取while(true){//一个字符一个字符的读char c (char) br.read();//一直读取到结束符\3if(c \3)break;list.add(c);}//拼接数据StringBuilder sb new StringBuilder();for (char c : list){sb.append(c);}request.data sb.toString();return request;}//客户端发送请求到服务端public void clientWrite(OutputStream os) throws IOException {PrintWriter pw new PrintWriter(os);pw.println(type);pw.println(url);pw.write(data\3);// 4-2.有缓冲区的IO操作真正传输数据需要刷新缓冲区pw.flush();}Overridepublic String toString() {return Request{ type type , url url \ , data data \ };}public Integer getType() {return type;}public void setType(Integer type) {this.type type;}public String getUrl() {return url;}public void setUrl(String url) {this.url url;}public String getData() {return data;}public void setData(String data) {this.data data;} }4.7.4响应类 按照约定的响应协议封装响应类 每个字段为一个属性响应状态码完成客户端解析响应封装按约定的方式读先按行读取第1个字段再按结束符读第2个字段完成服务端发送响应封装按约定的方式写第1个字段按行输出第2个字段以\3结束 package org.example.tcp.demo3; import java.io.*; import java.util.ArrayList; import java.util.List; public class Response {//响应的状态码200表示操作成功404表示没有找到该路径的文件或目录private int status;//数据private String data;//客户端解析服务端返回的响应数据public static Response clientParse(InputStream is) throws IOException {BufferedReader br new BufferedReader(new InputStreamReader(is, UTF8));Response response new Response();response.status Integer.parseInt(br.readLine());//使用list保存字符ListCharacter list new ArrayList();//数据循环读取while(true){//一个字符一个字符的读char c (char) br.read();//一直读取到结束符\3if(c \3)break;list.add(c);}//拼接数据StringBuilder sb new StringBuilder();for (char c : list){sb.append(c);}response.data sb.toString();return response;}//服务端返回响应给客户端public void serverWrite(OutputStream os) throws IOException {PrintWriter pw new PrintWriter(new OutputStreamWriter(os, UTF-8));pw.println(status);pw.write(data\3);// 4-2.有缓冲区的IO操作真正传输数据需要刷新缓冲区pw.flush();}Overridepublic String toString() {return Response{ status status , data data \ };}public int getStatus() {return status;}public void setStatus(int status) {this.status status;}public String getData() {return data;}public void setData(String data) {this.data data;} }4.7.5TCP服务端 以下完成服务端代码 ServerSocket.accept() 为建立客户端服务端连接的方法为提高效率使用多线程先要解析请求数据即 Request 已封装好的服务端解析请求返回 Request 对象返回响应数据需要根据不同的请求字段做不同的业务处理并返回对应的响应内容 如果操作的url路径再服务端根目录 E:/TMP 下找不到则返回响应状态码404正常执行完返回200响应状态码要注意根据不同操作类型来执行不同的业务 package org.example.tcp.demo3; import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.file.Files; import java.util.UUID; public class TcpServer {//服务器socket要绑定固定的端口private static final int PORT 8888;//本地文件目录要展示的根路径private static final String BASE_PATH E:/TMP;public static void main(String[] args) throws IOException {// 1.创建一个服务端ServerSocket用于收发TCP报文ServerSocket server new ServerSocket(PORT);// 不停的等待客户端连接while(true) {// 2.等待客户端连接注意该方法为阻塞方法Socket socket server.accept();new Thread(new Runnable() {Overridepublic void run() {try {System.out.println(------------------------------------ ---------------);System.out.println(客户端建立TCP连接...);System.out.printf(客户端IP%s%n, socket.getInetAddress().getHostAddress());System.out.printf(客户端端口号%s%n, socket.getPort());// 5.接收客户端的数据需要从客户端Socket中的输入流获取 InputStream is socket.getInputStream();// 解析为请求对象 Request request Request.serverParse(is);System.out.println(服务端收到请求request);// 6.根据请求处理业务处理完成返回响应对象 Response response build(request);// 7.返回响应给客户端通过客户端socket中的输出流发送响应数据 OutputStream os socket.getOutputStream();// 7-1.返回的响应内容按照约定格式输出响应对象中的内容 System.out.println(服务端返回响应response);response.serverWrite(os);// 7-3.双方关闭连接服务端是关闭客户端socket连接 socket.close();} catch (IOException e) {e.printStackTrace();}}}).start();}}//根据请求处理业务返回响应对象public static Response build(Request request){Response response new Response();response.setStatus(200);File url new File(BASE_PATHrequest.getUrl());//该路径的文件或目录不存在if(!url.exists()){response.setStatus(404);response.setData();return response;}try {switch (request.getType()){//1展示目录文件列表case 1: {File[] children url.listFiles();if(children null){response.setData();}else{//拼接要返回的数据文件列表 StringBuilder sb new StringBuilder();for (int i 0; i children.length; i) {File child children[i];//文件路径截取掉服务端本地路径前缀sb.append(child.getAbsolutePath().substring(BASE_PATH.length())\n);}response.setData(sb.toString());}break;}//2文件重命名case 2: {url.renameTo(new File(url.getParent()File.separatorrequest.getData()));break;}//3删除文件case 3: {url.delete();break;}//上传文件case 4: {//上传到请求的操作路径目录下保存的文件名简单的以随机字符串uuid生成即 可FileWriter upload new FileWriter(url.getAbsolutePath()File.separator UUID.randomUUID());upload.write(request.getData());upload.flush();upload.close();break;}//下载文件case 5: {String data new String(Files.readAllBytes(url.toPath()));response.setData(data);break;}}} catch (IOException e) {e.printStackTrace();}return response;} }4.7.6TCP客户端 以下为客户端代码 先要建立和服务端的连接连接服务端的IP和端口根据输入来构建请求数据 先接收操作类型和操作路径重命名操作时需要指定修改的文件名文件上传操作时需要指定上传的客户端本地文件路径 解析响应数据并根据响应来执行相应的业务我们这里暂时简单的解析为 Response 对象并打印即可 package org.example.tcp.demo3; import java.io.*; import java.net.Socket; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Scanner; public class TcpClient {//服务端IP或域名private static final String SERVER_HOST localhost;//服务端Socket进程的端口号private static final int SERVER_PORT 8888;public static void main(String[] args) throws IOException {// 准备要发送的数据这里调整为键盘输入作为发送的内容Scanner scanner new Scanner(System.in);while(true) {//根据键盘输入构造一个请求对象包含操作类型操作路径长度和数据Request request build(scanner);// 3.创建一个客户端流套接字Socket并与对应IP的主机上对应端口的进程建立连接Socket socket new Socket(SERVER_HOST, SERVER_PORT);// 4.发送TCP数据是通过socket中的输出流进行发送OutputStream os socket.getOutputStream();// 4-1.发送请求数据按照约定的格式输出请求对象中的内容System.out.println(客户端发送请求request);request.clientWrite(os);// 8.接收返回的响应数据通过socket中的输入流获取InputStream is socket.getInputStream();// 根据约定的格式获取响应数据Response response Response.clientParse(is);System.out.println(客户端收到响应response);// 9.双方关闭连接客户端关闭socket连接socket.close();}}//客户端发送请求时根据键盘输入构造一个请求对象public static Request build(Scanner scanner) throws IOException {System.out.println(--------------------------------------------------- );System.out.println(请输入要操作的类型1展示目录文件列表2文件重命名 3删除文件4上传文件5下载文件);Request request new Request();int type Integer.parseInt(scanner.nextLine());System.out.println(请输入要操作的路径);String url scanner.nextLine();String data ;//只需要操作类型和操作路径的请求长度和数据构造为空的if(type 2){//重命名操作需要输入重命名的名称System.out.println(请输入要重命名的名称);data scanner.nextLine();}else if(type 4){//文件上传需要提供上传的文件路径System.out.println(请输入要上传的文件路径);String upload scanner.nextLine();data new String(Files.readAllBytes(Paths.get(upload)));}else if(type ! 1 type !3 type!5){System.out.println(只能输入1-5的数字请重新输入);return build(scanner);}request.setType(type);request.setUrl(url);request.setData(data);return request;} }4.8长连接 vs 短连接 短连接客户端每次给服务器发消息先建立连接再发送请求读取响应关闭连接。下次再发送则重新建立连接。(连一次读一次断一次) 长连接客户端每次建立连接之后连接不着急断开然后再发送请求读取响应再发送请求读取响应若干轮之后客户端确实短时间之内不再需要使用这个连接了此时再断开。(连一次读多次不需要再断开) 在具体代码中我们将里面的 while (true){}这个条件去掉就是短连接啦 如果带上 while (true){} 就是长连接 4.9UDP vs TCP UDP 无连接(发微信发qq信息) 不可靠传输(没有已读功能) 面向数据报 (数据传输则以一个个的数据报为基本单位。 一个数据报可能是若干个字节带有一定的格式的) 全双工(一个通信通道可以双向传输。 既可以发送又可以接收)- 一根网线里面其实有 8 根线 TCP 有连接(打电话) 可靠传输(有已读功能(例如抖音消息已读不回QAQ)) 面向字节流(数据传输就和文件读写IO 类似流式的) 全双工(一个通信通道可以双向传输。 既可以发送又可以接收) - 一根网线里面其实有 8 根线 感谢各位读者的阅读本文章有任何错误都可以在评论区发表你们的意见我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞你的每一次鼓励都是作者创作的动力哦
http://www.hkea.cn/news/14296064/

相关文章:

  • wordpress全站ssl平台公司代理注册
  • 如何在木上做网站军民融合网站建设
  • 厦门商城网站开发网络运营师资格证
  • 如何做flash游戏下载网站甘肃兰州做网站
  • 网站建设方案的内容手机网站开发如何设置触摸功能
  • 做美工需要知道的设计网站wordpress 开源模板
  • python做网站后台网页设计与网站建设...
  • 印刷网站建设价格前端seo是什么意思
  • 网站建设昆明包装设计兰州网站分类导航
  • 石材公司网站源码电商网站建设实验心得
  • 网站营销推广策划方案兰州网站推广建设
  • 广州外贸网站建设wordpress query.php
  • 濮阳市网站怎么做宣传wordpress建站心得
  • 怎么管理网站的内容传媒公司logo
  • 店铺网页设计尺寸富阳网站seo价格
  • 洛阳霞光建设网站wordpress 一些数据表不可用
  • 潮阳网站建设公司如何在网上推广信用卡
  • 能发外链的网站wordpress折叠代码
  • 东莞整站排名做公司网站哪里好
  • 买衣服的网站排行榜11免费建网站
  • 大数据 做网站流量统计网站建设客户案例
  • 小程序和网站的区别关于产品网站建设的问题
  • 网站的空间和域名是啥运城网站建设报价
  • 20个中国风网站设计欣赏免费下载中国移动app
  • 青岛网站seo收费标准东莞seo建站优化公司
  • 宁波网站建设哪里便宜做易买网网站项目心得体会
  • ajax网站开发技术微商城网站建设哪家好
  • 馆陶县网站重庆网站建开发
  • 中小型电子商务网站拓展培训东莞网站建设
  • 本科自考最快多久拿证上海网站代优化