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

看设计比较好的网站在线装修设计平台

看设计比较好的网站,在线装修设计平台,青岛专业网络推广定制,网页设计免费素材Java网络编程:(socket API编程:TCP协议的 socket API – 服务器端处理请求的三个步骤) 文章目录Java网络编程:(socket API编程:TCP协议的 socket API -- 服务器端处理请求的三个步骤&#xff09…

Java网络编程:(socket API编程:TCP协议的 socket API – 服务器端处理请求的三个步骤)

文章目录

    • Java网络编程:(socket API编程:TCP协议的 socket API -- 服务器端处理请求的三个步骤)
  • 观前提醒
  • 1. 程序准备代码:
  • 2. 根据处理请求的三个步骤,编写代码
    • 2.1 读取请求,并解析请求数据
      • 输入流读取请求
        • 注意:
      • Scanner 读取请求
      • 填入不同参数,Scanner 所做的工作
      • 针对本程序(读取请求)
      • 读取请求前,可以进行判断
      • 总结
    • 2.2 根据请求,计算响应(服务器最关键的逻辑)
    • 2.3 把响应返回给客户端
      • 纯字节流方式(write)
      • PrintWriter 写数据
      • 遗留的问题:
      • 使用原理
    • 2.4 打印日志,显示信息
  • 3. 关于这个程序的一些问题:
    • 1. 一次请求相当于一次连接?
  • 4. 总结

观前提醒

本篇博客,是从 Java网络编程:(Java网络编程:(socket API编程:TCP协议的 socket API – 回显程序的服务器端程序的编写) 这篇博客分离出来的,需要你看完这篇博客,再过来看这篇博客。

1. 程序准备代码:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;public class TCPEchoServer {private ServerSocket serverSocket = null;public TCPEchoServer(int port) throws IOException {this.serverSocket = new ServerSocket(port);}public void start() throws IOException {System.out.println("启动服务器!");//        服务器需要不断的读取客户端的请求数据,用一个死循环实现这一点while(true){// 对于 TCP 来说,需要先处理客户端发来的连接// clientSocket 这个变量,就表示和服务器和客户端进行交流的一个对象,// 后续,就通过读写 clientSocket ,和客户端进行通信Socket clientSocket = serverSocket.accept();
//            处理一个客户端的请求和响应processConnect(clientSocket);}}//    处理一个客户端的连接
//    一个客户端,可能会发送多个请求,就要处理多个请求,得到多个响应private void processConnect(Socket clientSocket) {
//        打印一个日志,输出 clientSocket 的 IP和端口号System.out.printf("[%s : %d] 客户端连接成功,客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()){//            一个客户端,可能会发送多个请求,就要处理多个请求,得到多个响应
//            所以,需要使用 while 循环,处理多次
//            不知道客户端到底会发送多少个请求,所以,使用死循环while(true){
//            这里的工作分为三个步骤:
//                1. 读取请求,并解析请求数据//                2. 根据请求,计算响应(服务器最关键的逻辑)//                3. 把响应返回给客户端}} catch (IOException e) {throw new RuntimeException(e);}}}

2. 根据处理请求的三个步骤,编写代码

2.1 读取请求,并解析请求数据

输入流读取请求

读取请求这块,TCP 这里,是通过 InputStream 这个输入流对象,提供的 read 方法来读取的。
在这里插入图片描述
这一条语句,尤其需要注意:

String request = new String(requestByte,0,byteNum);
注意:

第三个参数,必须是读取请求后,读取到的有效字节个数(代码中的 byteNum),不能是 requestByte.length!!!

原因分析:
requestByte.length:表示的是你定义 requestByte 这个字节数组的长度,如果你用这个参数构造 String,会将空白的字符,一起构造了。
我们需要的是有效的字节个数

使用 read 方法,读取请求之后,会返回一个整数,这个整数,就是读取到的实际字节个数,就是有效的字节个数

假定,我们程序是写完了的:如果你使用 requestByte.length 这个,最后的结果会是这样的:
在这里插入图片描述
会将空余的字符,都打印出来了,这是不符合实际要求的。

这个操作,我们可以使用一个更直接的方式:Scanner

Scanner 读取请求

Scanner 这个类,不仅可以从控制台读取用户输入的数据,也能读取文件中的数据,还能读取网络中的请求。

为什么呢?
其实,Scanner 的构造方法,填入的是一个 InputStream 对象。

平常,我们想要从控制台这边读取用户输入的数据的时候,是这样子写的:
在这里插入图片描述
但当我们按住左下角的Ctrl + 鼠标左键,点击 in 的时候,会发现:
在这里插入图片描述
in,实际上就是一个 InputStream类 实例出来的对象

所以, Scanner 的构造方法填入的是一个 InputStream 对象

填入不同参数,Scanner 所做的工作

  1. 填入 System.in 这个参数
    往 Scanner 的构造方法中,填入 System.in 这个参数,就是控制台中读取用户输入的数据。
    在这里插入图片描述
  2. 填入 File 对象
    往 Scanner 的构造方法中,填入 File对象,就是指定的目标文件中读取数据。
    在这里插入图片描述
  3. 填写 InputStream 对象(本程序使用的参数)
    往 Scanner 的构造方法中,填写从 Socket 获取到的 InputStream 对象,就是从指定的网络输入流中,读取数据

如果是获取到客户端(clientSocket)的输入流对象,就可以通过 Scanner,读取从客户端获取到的输入流对象中的字节数据。
在这里插入图片描述

针对本程序(读取请求)

对于我们这个回显程序的读取来说,我们可以将我们从 clientSocket 中,获取到的 InputStream 输入流对象,输入给 Scanner 的构造方法中:
在这里插入图片描述
这个代码,就是把 从 clientSocket 这个 Socket对象 中获取到的 输入流对象(inputStream)传给了 Scanner对象(scanner),后续,我们就可以从 scanner 里面,直接读取到客户端发送过来的请求里面的内容。

相当于,我们不使用 InputStream类 提供的 read方法,而是将
输入流对象(inputStream),传给了 Scanner对象(scanner),使用 Scanner类 来读取请求中的内容
在这里插入图片描述
并且,可以直接转化为字符串,一步到位。

读取请求前,可以进行判断

我们在读取客户端的请求前,可以判断一下:是否还有请求可以读,如果有,就继续读,如果没有,就跳出循环,结束本次对客户端的请求处理。

并且打印一个日志,显示 服务器 和 客户端,断开了连接。

代码:

if (!scanner.hasNext()){
//客户端没有请求发送过来了,就不需要继续读取请求,并处理了
//可以断开和客户端的连接(结束循环)//打印一个日志,显示 服务器 和 客户端,断开了连接
System.out.printf("[%s : %d] 断开连接,客户端下线!\n",clientSocket.getInetAddress(),clientSocket.getPort());break;
}

在这里插入图片描述
客户端没有请求发送过来了,就可以结束循环,结束 processConnect方法,断开和客户端的连接了。

总结

这一步操作,我们主要讲了,如何改变读取的方式采用 Scanner 的方式,对客户端发送过来的请求进行读取。

这一种方式,能够简化代码,更加快捷的将请求数据转化为字符串,方便后续操作。

到目前为止的代码(仅截取 processConnect 方法内的代码):

//    处理一个客户端的连接
//    一个客户端,可能会发送多个请求,就要处理多个请求,得到多个响应private void processConnect(Socket clientSocket) {
//        打印一个日志,输出 clientSocket 的 IP和端口号System.out.printf("[%s : %d] 客户端连接成功,客户端上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());try(InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()){Scanner scanner = new Scanner(inputStream);
//            一个客户端,可能会发送多个请求,就要处理多个请求,得到多个响应
//            所以,需要使用 while 循环,处理多次
//            不知道客户端到底会发送多少个请求,所以,使用死循环while(true){
//            这里的工作分为三个步骤:
//                1. 读取请求,并解析请求数据////                使用 InputStream 提供的 read 方法读取数据
//                byte[] requestByte = new byte[1024];
//                inputStream.read(requestByte);
////                为了后续的处理更加方便,需要手动转换为 String
//                String request = new String(requestByte,0,requestByte.length);//                使用 Scanner 读取请求if (!scanner.hasNext()){
//                    客户端没有请求发送过来了,就不需要继续读取请求,并处理了
//                    可以断开和客户端的连接(结束循环)break;}String request = scanner.next();//                2. 根据请求,计算响应(服务器最关键的逻辑)//                3. 把响应返回给客户端}} catch (IOException e) {throw new RuntimeException(e);}}

2.2 根据请求,计算响应(服务器最关键的逻辑)

我们这个程序,是回显程序,客户端的请求是什么,返回给客户端的响应就是什么。

我们这里,用一个 process 方法,将赋值的过程,进行封装,方便后续进行更改计算响应的逻辑。
在这里插入图片描述

2.3 把响应返回给客户端

纯字节流方式(write)

我们需要将响应,根据 Socket对象(clientSocket),获取到的字节输出流对象(outputStream)提供的 write 方法,写回到客户端中,所以,我们的写法是:
在这里插入图片描述
这种方式,是以字节流的方式,进行发送的。

PrintWriter 写数据

但是,我们还有一种写法:使用 PrintWriter,这和上面,使用 Scanner 的方式类似。

我们将 OutputStream 这个字节输出流,所实例化的对象 outputStream,传给 PrintWriter 这个类实例出来的对象 ,writer。
在这里插入图片描述
后续,我们就可以使用 writer 这个对象,将响应,写回(发送)给客户端

并且,是以字符流的方式,进行发送的。
也就是,直接将 String 类型的响应数据,返回给客户端,不需要再获取到 String 类型的响应数据中的字节数据。

使用 writer 这个对象,将响应,写回(发送)给客户端:
在这里插入图片描述

遗留的问题:

这个问题,出自于 writer.println(response); 这一步代码,至于是什么问题,当我们后续启动程序的时候,就知道了。

使用原理

这种使用方法,其实和我们将数据输出到控制台是差不多的。

我们使用打印语句:System.out.println();中间的out,本质上,是一个 OutputStream 实例化的对象
在这里插入图片描述
所以,使用 PrintWriter 的时候,和使用 Scanner 读取请求的时候,是差不多的。

PrintWriter参数,填写从 Socket 获取到的 OutputStream 对象,就是从指定的网络输出流中,写入数据

2.4 打印日志,显示信息

我们可以打印日志,显示 客户端发送的请求 和 服务器端返回的响应信息。

使用 C语言 的 printf 方法,进行格式化的打印输出。

//                4.打印日志,显示 客户端发送的请求 和 服务器端返回的响应信息
System.out.printf("[%s : %d] 请求(req):%s,响应信息(resp):%s \n",
clientSocket.getInetAddress(),
clientSocket.getPort(),
request,response);

3. 关于这个程序的一些问题:

1. 一次请求相当于一次连接?

答:不是的!!!

我们这个程序,首先,需要先和客户端建立连接,之后,这一次的连接中,客户端可以发送多个请求

好比我们现实生活中打电话:
打一次电话,相当于一次连接,这一次连接,你可以只说一句话,就挂断电话(断开连接)。
可以说很多句话,才挂断电话

打一次电话,就说一句话就挂断电话,相当于一次连接,只有一次请求,这种方式,也叫做:短连接
打一次电话,说很多句话,才挂断电话,相当于一次连接多次请求,这种方式,也叫做:长连接

现实生活中,更多的是 长连接,因为短链接,比较消耗性能
这也是服务器程序,主流的写法。

4. 总结

这篇博客,主要是按照三个步骤,对客户端发送过来的请求,进行处理,这篇博客看完之后,返回这篇博客:
Java网络编程:(socket API编程:TCP协议的 socket API – 回显程序的服务器端程序的编写)

最后,如果这篇博客能帮到你的,请你点点赞,有写错了,写的不好的,欢迎评论指出,谢谢!

http://www.dtcms.com/a/483884.html

相关文章:

  • 网站建设目标分析学校网站建设工作方案
  • 【Linux】Linux驱动开发与BSP开发:嵌入式系统的两大基石
  • 郑州机械网站建设张家港网站制作服务
  • 动叫建个网站刷排名郑州高端做网站
  • 波矢 行波 和 相速度推导
  • LeetCode算法日记 - Day 72: 下降路径最小和、珠宝的最高价值
  • 天津专业智能建站wordpress 转换app
  • 周口市住房和城乡建设局门户网站wordpress邮件服务器怎么设置
  • 新版 网站在建设中...工信部 网站 备案
  • Flutter---showCupertinoDialog
  • 万州做网站seo优化一般包括哪些
  • 网站建设优化兼职在家漯河网站建设费用
  • 学校网站的英文一个人如何注册公司
  • 哪些网站用php余姚网站建设设计服务
  • PS成长之路⑧:如何判断生成何种需求类型满足场景需求
  • 如何把资料上传到网站威海城乡建设局网站
  • 专业制作网站 上海模版做网站多少钱
  • 快速掌握【Redis】Set:从基础命令到内部编码
  • [Linux系统编程——Lesson13.自定义shell(讲解原理)]
  • 微信开放平台官方网站家电电商平台排名
  • 贵州建设厅考试网站二建成绩自己动手建设公司门户网站
  • 湛江网站建设方案托管个人网页设计html加js代码
  • 崇左网站建设网站如何做绿标
  • 湛江制作网站公司互联网站的建设维护营销
  • 陪跑教学大纲:PowerBI QuickBI FineBI 数据运营 面试 简历修改等
  • 做海报有什么好的网站推荐网络营销网站建设诊断报告
  • 郑州网站推建设河南省建设科技会网站
  • 电商网站建设方案道客巴巴北京提供24小时医疗服务
  • 网站打开是别人的哪个网站做设计兼职不用压金
  • MySQL新增插入,重复更新操作业务实现