wordpress建站详解wordpress 视频播放
wordpress建站详解,wordpress 视频播放,用代码做网站,申请个人手机网站空间#x1f52d; 嗨#xff0c;您好 #x1f44b; 我是 vnjohn#xff0c;在互联网企业担任 Java 开发#xff0c;CSDN 优质创作者 #x1f4d6; 推荐专栏#xff1a;Spring、MySQL、Nacos、Java#xff0c;后续其他专栏会持续优化更新迭代 #x1f332;文章所在专栏 嗨您好 我是 vnjohn在互联网企业担任 Java 开发CSDN 优质创作者 推荐专栏Spring、MySQL、Nacos、Java后续其他专栏会持续优化更新迭代 文章所在专栏网络 I/O 我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识 向我询问任何您想要的东西IDvnjohn 觉得博主文章写的还 OK能够帮助到您的感谢三连支持博客 代词: vnjohn ⚡ 有趣的事实音乐、跑步、电影、游戏 目录 前言阻塞式 I/O 模型图解分析源码实践Socket 服务端代码Socket 客户端代码流程说明 命令简要解析stracesocketbindlistenaccept 总结 前言
Unix/Linux 下可用的 I/O 模型有以下五种
阻塞式 I/O非阻塞式 I/OI/O 复用(select、poll)信号驱动式 I/O(SIGIO)异步 I/O
在 Linux 中操作内核时所有的无非三种操作分别是输入、输出、报错输出 0-输入 1-输出 2-报错输出 一个输入操作通常包括两个不同的阶段
等待数据准备好从内核向进程复制数据
对于一个套接字Socket的输入操作第一步通常涉及等待数据从网络中当所等待分组到达时它被复制到内核中的某个缓冲区第二步就是把数据从内核缓冲区复制到应用进程缓冲区
阻塞式 I/O 模型
最流行的 I/O 模型是阻塞式 I/O (Blocking I/O) 模型在默认的不加任何附加值的情况下所有的套接字都是阻塞的以数据报套接字作为例子如下 数据准备好读取的概念比较简单要么整个数据报已经收到要么还没有
recvfrom 函数被视为系统调用区分应用空间、内核空间无论它如何实现一般都会从在应用进程空间中运行切换到在内核空间中运行一段时间之后再切换回来
进程调用 recvfrom 其系统调用直到数据到达且被复制到应用进程的缓冲区中或者发生错误才返回。最常见的错误是系统调用被信号中断 进程从调用 recvfrom 开始到它返回的整段时间内是被阻塞的recvfrom 成功返回后应用进程开始处理数据报 图解分析 查询 TCP、Socket 网络条目信息netstat -natp
当有新的连接进来时主线程负责执行 accept 连接客户端clone 出一个线程去 accept/read等待其他客户端连接时是阻塞的读取客户端数据也是阻塞的BIO 采用的处理方式主线程阻塞去等待客户端连接为每个客户端分配一个子线程去阻塞读取数据
在本文中会涉及到一些函数操作所有的函数大致操作流程如下图 源码实践
Socket 服务端代码
package org.vnjohn.bio.server;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;/*** author vnjohn* since 2023/11/25*/
public class SocketServer {public static void main(String[] args) throws IOException {ServerSocket server new ServerSocket(8090);System.out.println(step1: new ServerSocket(8090));while (true) {Socket client server.accept();System.out.println(step2client\t client.getPort());new Thread(new Runnable() {Socket socket;public Runnable setSocket(Socket socket) {this.socket socket;return this;}Overridepublic void run() {try {InputStream inputStream socket.getInputStream();BufferedReader reader new BufferedReader(new InputStreamReader(inputStream));while (true) {System.out.println(reader.readLine());}} catch (IOException e) {e.printStackTrace();}}}.setSocket(client)).start();}}
}Socket 客户端代码
package org.vnjohn.bio.client;import java.io.*;
import java.net.Socket;/*** author vnjohn* since 2023/11/25*/
public class SocketClient {public static void main(String[] args) {try {Socket client new Socket(172.16.249.10, 9090);client.setSendBufferSize(20);// false 优化,true 不优化client.setTcpNoDelay(true);client.setOOBInline(false);OutputStream out client.getOutputStream();InputStream in System.in;BufferedReader reader new BufferedReader(new InputStreamReader(in));while (true) {String line reader.readLine();if (line ! null) {byte[] bb line.getBytes();for (byte b : bb) {out.write(b);}}}} catch (IOException e) {e.printStackTrace();}}
}流程说明 172.16.249.10 是之前作为 node1 节点所在 IP 将以上两个 java 源文件上传到 node1 虚拟节点上所在目录/opt/java 1、在虚拟节点上安装好 Java 环境 2、将源文件所在的 package 包名通过 vim 命令将 package 包名删除首行. 3、将 Java 源文件进行编译为 .class 文件 javac SocketServer.java、javac SocketClient.java 1、追踪应用程序与操作系统中的交互信息 cd /opt/java strace -ff -o out java SocketServer 执行该追踪命令以后会在 /opt/java 下生成几个 out 前缀文件所有的 out 前缀所对应的后缀是所属的进程 pid 号 通过 jps 命令查看当前所运行的 SocketServer 所占用的 pid 进程它能够对应上所输出的文件. 但实际上生成的与操作系统交互信息都不会在这个文件中它会 clone 一个子进程去负责 accept 2、通过 vim 命令查看对应的 out.28979 所输出的内容 结合以上输出的内容我们重点是要关注 out.28980 文件的内容 在此处能够发生输出的文件中出现了核心的三个网络相关函数调用分别是socket、bind、listen在后一节会简要的介绍这些函数的作用
3、通过我们能构建的 node2 节点172.16.249.11来充当 Socket 客户端的角色看它与服务端建立连接以后在 out.28980 文件中会出现什么内容 首先是在 node2 节点通过 java 命令直接运行该 Java 程序 随即观察 node1 节点所开启的服务端窗口会出现双方建立连接成功的系统输出 当前 node1 服务端为其客户端分配了一个 32900 端口进行后续两者之间的通信
out.28980 文件的内容如下 通过 accept 系统调用为其客户端分配了一个 32900 端口IP172.16.249.11分配的 socketfd 文件描述符为 6
4、如何观察进程的所有文件描述符信息 通过命令ls -l /proc/28980/fd 28980 是对应的 pid 进程号 Server Accept分配的 fd 为 5
Client 建立连接成功分配的 fd 为 6 通过命令netstat -natp 查询 Socket/TCP 网络信息 命令简要解析
当然要学习 Linux 中内核一些核心参数命令的使用可以借助 man pages 帮助文档来进行阅读 man pagesyum install man pthread man pagesyum -y install man-pages strace
Linux 中 strace 命令能够很方便的帮助到你追踪到一个程序所执行的系统调用信息 查看 strace 使用文档man strace 在最简单的情况下strace 运行指定的命令直到退出它拦截并记录进程所调用的系统调用、进程所接收的信号 每个系统调用的名称它的参数和返回值都会被打印到标准错误或者用 -o 参数选项输出到指定的文件中 它有很多的参数选项如下
-a column对齐特定列中的返回值默认列 40-i在系统调用时打印指令指针-o filename将跟踪输出写入文件的文件名中而不是写入到 stderr 标准错误如果同时提供了 -ff 选项则使用 pid 文件的形式通过管道的方式进行传输写入-A以追加的模式打开 -o 选项中提供的文件-q抑制有关附加、分离等信息当输出被重定向到文件并且直接运行命令而不是附加命令时会发生这种情况-qq如果给出两次则抑制有关进程退出状态的消息-r在进行每个系统调用时打印一个相对时间戳记录了连续系统调用开始的时间差-s strsize指定要打印的最大字符串的大小默认为 32-t用挂钟时间作为每一行跟踪的前缀-tt若给出两次打印的时间将包括微妙-ttt若给定三次则打印的时间将包括微妙并且前导部分将作为自 epoch 以来的秒数打印-T显示花费在系统调用上的时间这将记录每个系统调用开始和结束之间的时间差-x以十六进制字符串格式打印所有的非 ascii 字符串-xx以十六进制字符串格式打印所有字符串-X format设置命名变量和标志的打印格式支持的格式值有 raw未经解码的原始数字输出 abbrev输出一个命名的常量或一组标志而不是找到的原始数字这是默认的字符行为 verbose输出原始值和解码后的字符串 -y打印与文件描述符参数关联的路径-yy打印与套接字文件描述符相关的协议特定信息以及与设备文件描述符相关的块/字符设备号 还有一些统计指标的参数选项可以查看帮助文档进行使用. socket 查看 socket 命令帮助文档man 2 socket int socket(int domain, int type, int protocol); 包裹函数Socket() 创建用于通信的端点并返回套接字描述符 实践部分socket(AF_INET6, SOCK_STREAM, IPPROTO_IP) 5
bind 查看 bind 命令帮助文档man 2 bind int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); 当使用 socket 创建套接字时它存在于名称空间中地址族中但没有给它分配地址 bind() 将 addr 指定的地址分配给文件描述符 sockfd 引用的套接字Addrlen 指定 addr 指向的地址结构大小以字节为单位
在传统上bind 此操作称为 “为套接字分配名称”
实践部分 bind(5, {sa_familyAF_INET6, sin6_porthtons(8090), inet_pton(AF_INET6, “::”, sin6_addr), sin6_flowinfohtonl(0), sin6_scope_id0}, 28) 0 5原始套接字 sockfd AF_INET6协议类型 8090原始套接字端口号 listen 查看 listen 命令帮助文档man 2 listen int listen(int sockfd, int backlog); 将 sockfd 引用的套接字标记为被动套接字也就是说将使用 accept(2) 来接受传入的连接请求 sockfd 参数是一个文件描述符它引用 SOCK_STREAM 或 SOCK_SEQPACKET 类型的套接字
backlog 参数定义 sockfd 挂起链接队列可能增长到的最大长度若一个连接请求在队列已满时到达客户端可能会收到一个带有 ECONNREFUSED 指示的错误或者如果底层协议支持重传(TCP)请求可能会被忽略以便稍后重试连接成功
实践部分listen(5, 50) 监听此文件描述符并为其分配一个长度为 50 的链接队列队列满了以后会有 SYN_RECV 状态的网络条目出现 accept 查看 accept 命令帮助文档man 2 accept int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); accept() 系统调用用于基于连接的套接字类型SOCK_STREAM、SOCK_SEQPACKET它提取了侦听套接字 sockfd 挂起链接队列上的第一个连接请求将创建一个新连接套接字并返回一个引用该套接字的新文件描述符新创建的套接字不在监听范围内状态。原始套接字 sockfd 不受此调用的影响 实践部分 accept(5, {sa_familyAF_INET6, sin6_porthtons(32900), inet_pton(AF_INET6, “::ffff:172.16.249.11”, sin6_addr), sin6_flowinfohtonl(0), sin6_scope_id0}, [28]) 6 5原始套接字 sockfd AF_INET6协议类型 172.16.249.11新 sockfd 文件描述符所在地址 6新套接字 sockfd 总结
该篇博文主要介绍的是 I/O 模型中的阻塞 I/O - BIO简要分析了 BIO 流程图及相关系统函数调用通过实践代码的方式来分析阻塞 I/O 在系统调用中所涉及到的流程最后介绍了相关联的系统函数strace、socket、bind、listen、accept希望能够得到你的支持感谢三连
四元组唯一源 IP、源端口、目标 IP、目标端口 愿你我都能够在寒冬中相互取暖互相成长只有不断积累、沉淀自己后面有机会自然能破冰而行 博文放在 网络 I/O 专栏里欢迎订阅会持续更新
如果觉得博文不错关注我 vnjohn后续会有更多实战、源码、架构干货分享
推荐专栏Spring、MySQL订阅一波不再迷路
大家的「关注❤️ 点赞 收藏⭐」就是我创作的最大动力谢谢大家的支持我们下文见
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/92315.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!