前端技术
HTML
CSS
Javascript
前端框架和UI库
VUE
ReactJS
AngularJS
JQuery
NodeJS
JSON
Element-UI
Bootstrap
Material UI
服务端和客户端
Java
Python
PHP
Golang
Scala
Kotlin
Groovy
Ruby
Lua
.net
c#
c++
后端WEB和工程框架
SpringBoot
SpringCloud
Struts2
MyBatis
Hibernate
Tornado
Beego
Go-Spring
Go Gin
Go Iris
Dubbo
HessianRPC
Maven
Gradle
数据库
MySQL
Oracle
Mongo
中间件与web容器
Redis
MemCache
Etcd
Cassandra
Kafka
RabbitMQ
RocketMQ
ActiveMQ
Nacos
Consul
Tomcat
Nginx
Netty
大数据技术
Hive
Impala
ClickHouse
DorisDB
Greenplum
PostgreSQL
HBase
Kylin
Hadoop
Apache Pig
ZooKeeper
SeaTunnel
Sqoop
Datax
Flink
Spark
Mahout
数据搜索与日志
ElasticSearch
Apache Lucene
Apache Solr
Kibana
Logstash
数据可视化与OLAP
Apache Atlas
Superset
Saiku
Tesseract
系统与容器
Linux
Shell
Docker
Kubernetes
[ReactJS 动画库开发实践 ]的搜索结果
这里是文章列表。热门标签的颜色随机变换,标签颜色没有特殊含义。
点击某个标签可搜索标签相关的文章。
点击某个标签可搜索标签相关的文章。
转载文章
...研发前沿还是日常运维实践,深入理解并正确运用NTP及其他高精度时间同步协议都是不可或缺的一环。
2023-03-01 12:56:47
112
转载
Hadoop
...新红利的同时,企业和开发者还需审慎评估自身的安全策略和技术选型。 总之,随着技术的不断发展,HDFS及其相关生态正经历着深刻的变革。未来,我们期待看到更多创新性的解决方案涌现出来,助力各行各业更好地应对数字化转型带来的挑战。
2025-05-04 16:24:39
102
月影清风
转载文章
... , 只捕获感兴趣的开发包/ int promisc; / 表示网卡模式 , 如果是非零, 就把此网卡设置为混杂模式 ; 否则 , 设为非混杂模式 . 默认值为1/ int one_loop_less; / 初始值为 0/ int pcap_timeout; / 表示捕获数据返回的时间 , 以毫秒计算. 实际上它表示的就是 Libpcap 函数中的 pcap_open_live函数的 timeout 参数 , 默认值 1024/ }; / 返回值 : 调用成功返回 1,失败返回 0 参 数 : 无 功 能 : 对 Libnids 初始化, 这是所有设计基于 Libnids 的程序最开始调用的函数 . 它的主要内容包括打开网络接口 , 打开文件 , 编译过滤规则 , 判断网络链路层类型, 进行必要的初始化工作 / int nids_init (void); / 返回值 : 无 参 数 : 回调函数名字 功 能 : 注册一个能够检测所有 IP 数据包的回调函数, 包括 IP 碎片 .e.g nids_register_ip_frag(ip_frag_function); void ip_frag_function(struct ip a_packet,int len) a_packet 表示接收的IP 数据包 len 表示接收的数据包长度 此回调函数可以检测所有的IP 数据包 , 包括 IP 碎片 / void nids_register_ip_frag (void ()); // / 返回值 : 无 参 数 : 回调函数名字 功 能 : 注册一个回调函数 , 此回调函数可以接收正常的IP 数据包 .e.g nids_register_ip_frag(ip_frag_function); void ip_frag_function(struct ip a_packet) a_packet 表示接收的IP 数据包 此回调函数可以接收正常的IP 数据包 , 并在此函数中对捕获数到的 IP数据包进行分析 . / void nids_register_ip (void ()); // / 返回值 : 无 参 数 : 回调函数 功 能 : 注册一个 TCP 连接的回调函数. 回调函数的类型定义如下 : void tcp_callback(struct tcp_stream ns,void param) ns 表示一个TCP 连接的所有信息 , param 表示要传递的参数信息 , 可以指向一个 TCP连接的私有数据 此回调函数接收的TCP 数据存放在 half_stream 的缓存中 , 应该马上取出来 ,一旦此回调函数返回 , 此数据缓存中存储的数据就不存在 了 .half_stream 成员 offset描述了被丢弃的数据字节数 . 如果不想马上取出来 , 而是等到存储一定数量的数据之后再取出来, 那么可 以使用函数nids_discard(struct tcp_stream ns, int num_bytes)来处理 . 这样回调函数返回时 ,Libnids 将丢弃缓存数据之前 的 num_bytes 字节的数据 .如果不调用 nids_discard()函数 , 那么缓存数据的字节应该为 count_new 字节 . 一般情况下, 缓存中的数据 应该是count-offset 字节 / void nids_register_tcp (void ()); / 返回值 : 无 参 数 : 回调函数 功 能 : 注册一个分析 UDP 协议的回调函数, 回调函数的类型定义如下 : void udp_callback(struct tuple4 addr,char buf,int len,struct ip iph) addr 表示地址端口信息buf 表示 UDP 协议负载的数据内容 len表是 UDP 负载数据的长度 iph 表示一个IP 数据包 , 包括 IP 首部 ,UDP 首部以及UDP 负载内容 / void nids_register_udp (void ()); / 返回值 : 无 参 数 : 表示一个 TCP 连接 功 能 : 终止 TCP 连接 . 它实际上是调用 Libnet的函数进行构造数据包 , 然后发送出去 / void nids_killtcp (struct tcp_stream ); / 返回值 : 无 参 数 : 参数 1 一个 TCP 连接 参数 2 个数 功 能 : 丢弃参数 2 字节 TCP 数据 , 用于存储更多的数据 / void nids_discard (struct tcp_stream , int); / 返回值 : 无 参 数 : 无 功 能 : 运行 Libnids, 进入循环捕获数据包状态. 它实际上是调用 Libpcap 函数 pcap_loop()来循环捕获数据包 / void nids_run (void); / 返回值 : 调用成功返回文件描述符 ,失败返回 -1 参 数 : 无 功 能 : 获得文件描述符号 / int nids_getfd (void); / 返回值 : 调用成功返回个数 ,失败返回负数 参 数 : 表示捕获数据包的个数 功 能 : 调用 Libpcap 中的捕获数据包函数pcap_dispatch() / int nids_dispatch (int); / 返回值 : 调用成功返回 1,失败返回 0 参 数 : 无 功 能 : 调用 Libpcap 中的捕获数据包函数pcap_next() / int nids_next (void); extern struct nids_prm nids_params; /libnids.c定以了一个全部变量 , 其定义和初始值在 nids_params/ extern char nids_warnings[]; extern char nids_errbuf[]; extern struct pcap_pkthdr nids_last_pcap_header; struct nids_chksum_ctl { / 描述的是计算校验和 , 用于决定是否计算校验和/ u_int netaddr; / 表示地址 / u_int mask; / 表示掩码 / u_int action; / 表示动作 , 如果是NIDS_DO_CHKSUM, 表示计算校验和; 如果是 NIDS_DONT_CHKSUM, 表示不计算校验和 / u_int reserved; / 保留未用 / }; / 返回值 : 无 参 数 : 参数 1 表示 nids_chksum_ctl 列表 参数 2 表示列表中的个数 功 能 : 决定是否计算校验和 . 它是根据数据结构nids_chksum_ctl 中的action 进行决定的 , 如果所要计算的对象不在列表中 , 则必须都要计算校验和 / extern void nids_register_chksum_ctl(struct nids_chksum_ctl , int); endif / _NIDS_NIDS_H / 本篇文章为转载内容。原文链接:https://blog.csdn.net/xieqb/article/details/7681968。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-02-08 17:36:31
306
转载
Mahout
...内容是基于实际的编程实践和理论知识的融合,旨在提供一个从概念到实现的全面指南。哎呀,当真要将这个系统或者项目实际铺展开来的时候,咱们得根据手头的实际情况,比如数据的个性、业务的流程和咱们的技术底子,来灵活地调整策略,让一切都能无缝对接,发挥出最大的效用。就像是做菜,得看食材的新鲜度,再搭配合适的调料,才能做出让人满意的美味佳肴一样。所以,别死板地照搬方案,得因地制宜,因材施教,这样才能确保我们的工作既高效又有效。
2024-09-06 16:26:39
59
月影清风
Hadoop
...一套丰富的接口,允许开发者自定义文件的操作行为。这就为实现跨访问控制协议迁移提供了可能性。 3.2 实现步骤 实现跨访问控制协议迁移大致分为以下几个步骤: (1)读取源系统的访问控制信息 第一步是获取源系统的访问控制信息。比如,如果你正在从Linux系统迁移到Windows系统,你需要先读取Linux上的ACL配置。 java // 示例代码:读取Linux ACL import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import java.io.IOException; public class AccessControlReader { public static void main(String[] args) throws IOException { Path path = new Path("/path/to/source/file"); FileSystem fs = FileSystem.get(new Configuration()); // 获取ACL信息 String acl = fs.getAclStatus(path).toString(); System.out.println("Source ACL: " + acl); } } 这段代码展示了如何使用Hadoop API读取Linux系统的ACL信息。可以看到,Hadoop已经为我们封装好了相关的API,调用起来非常方便。 (2)转换为目标系统的格式 接下来,我们需要将读取到的访问控制信息转换为目标系统的格式。比如,将Linux的ACL转换为Windows的NTFS权限。 java // 示例代码:模拟ACL到NTFS的转换 public class AclToNtfsConverter { public static void convert(String linuxAcl) { // 这里可以编写具体的转换逻辑 System.out.println("Converting ACL to NTFS: " + linuxAcl); } } 虽然这里只是一个简单的打印函数,但实际上你可以根据实际需求编写复杂的转换算法。 (3)应用到目标系统 最后一步是将转换后的权限应用到目标系统上。这一步同样可以通过Hadoop提供的API来完成。 java // 示例代码:应用NTFS权限 public class NtfsPermissionApplier { public static void applyPermissions(Path targetPath, String ntfsPermissions) { try { // 模拟应用权限的过程 System.out.println("Applying NTFS permissions to " + targetPath.toString() + ": " + ntfsPermissions); } catch (Exception e) { e.printStackTrace(); } } } 通过这三个步骤,我们就完成了从源系统到目标系统的访问控制协议迁移。 --- 四、实战演练 一个完整的案例 为了让大家更直观地理解,我准备了一个完整的案例。好啦,想象一下,我们现在要干的事儿就是把一个文件从一台Linux服务器搬去Windows服务器,而且还得保证这个文件在新家里的“门禁权限”跟原来一模一样,不能搞错! 4.1 准备工作 首先,确保你的开发环境中已经安装了Hadoop,并且配置好相关的依赖库。此外,还需要准备两台机器,一台装有Linux系统,另一台装有Windows系统。 4.2 编写代码 接下来,我们编写代码来实现迁移过程。首先是读取Linux系统的ACL信息。 java // 读取Linux ACL Path sourcePath = new Path("/source/file.txt"); FileSystem linuxFs = FileSystem.get(new Configuration()); String linuxAcl = linuxFs.getAclStatus(sourcePath).toString(); System.out.println("Linux ACL: " + linuxAcl); 然后,我们将这些ACL信息转换为NTFS格式。 java // 模拟ACL到NTFS的转换 AclToNtfsConverter.convert(linuxAcl); 最后,将转换后的权限应用到Windows系统上。 java // 应用NTFS权限 Path targetPath = new Path("\\\\windows-server\\file.txt"); NtfsPermissionApplier.applyPermissions(targetPath, "Full Control"); 4.3 执行结果 执行完上述代码后,你会发现文件已经被成功迁移到了Windows系统,并且保留了原有的访问控制设置。是不是很神奇? --- 五、总结与展望 通过这篇文章,我相信你对Hadoop支持文件的跨访问控制协议迁移有了更深的理解。Hadoop不仅是一个强大的工具,更是一种思维方式的转变。它就像个聪明的老师,不仅教我们怎么用分布式的思路去搞定问题,还时不时敲打我们:嘿,别忘了数据的安全和规矩可不能丢啊! 未来,随着技术的发展,Hadoop的功能会越来越强大。我希望你能继续探索更多有趣的话题,一起在这个充满挑战的世界里不断前行! 加油吧,程序员们!
2025-04-29 15:54:59
77
风轻云淡
ElasticSearch
...深刻体会到,作为一名开发者,不仅要掌握技术细节,还要学会从实际问题出发,找到最优解。NodeNotActiveException这个错误看着不起眼,但其实背后有不少门道呢!比如说,你的服务器硬件是不是有点吃不消了?集群那边有没有啥小毛病没及时发现?还有啊,咱们平时运维的时候是不是也有点松懈了?这些都是得好好琢磨的地方! 最后,我想说的是,技术学习的过程就像爬山一样,有时候会遇到陡峭的山坡,但只要坚持下去,总能看到美丽的风景。希望这篇文章能给大家带来一些启发和帮助!如果还有其他疑问,欢迎随时交流哦~
2025-03-14 15:40:13
64
林中小径
转载文章
...了更高要求,研究者和开发者必须熟悉并遵守相关法律法规,在确保知识产权不受侵犯的同时,寻求更高效、安全的技术解决方案。 同时,开源社区GitHub上出现了不少针对各类直播平台优化的视频下载工具项目,这些项目不仅实现了对.ts文件片段的智能解析和合并,还有的开始探索基于机器学习的方法来预测和模拟签名算法,以适应日益严格的反爬策略。例如,“Streamlink”是一款跨平台的命令行实用程序,能够从各种受保护的流媒体网站中提取并播放视频流,为研究人员提供了合法获取和处理流媒体数据的新思路。 此外,国家版权局近年来也加大了对网络侵权盗版行为的打击力度,并呼吁广大网民自觉抵制非法下载和传播他人作品的行为,倡导尊重原创、保护版权的社会风尚。在实际操作中,开发者应关注《信息网络传播权保护条例》等相关法规,确保个人或团队的研究活动既满足学术探究需求,又符合法律规定。 总之,面对流媒体视频下载与处理这一领域,我们既要掌握先进的技术方法以适应日新月异的网络环境,又要时刻保持对法律边界的敬畏之心,做到技术发展与法制建设相得益彰。
2023-12-18 11:34:00
119
转载
转载文章
...色叠加的原理进行创新实践。例如,荷兰艺术家埃舍尔借助颜色叠加创作出视错觉艺术作品,展示出二维空间内不同颜色相互作用产生的神奇效果。而在时尚界,设计师们通过面料上的颜色叠加与透明度变化,营造出丰富多变且极具层次感的视觉体验。 总的来说,颜色叠加这一基本原理不仅在科普实验中有生动体现,更在科技、教育、艺术等多个领域发挥着重要作用,不断推动着人类对色彩世界的深入理解和广泛利用。
2024-01-20 16:20:26
468
转载
转载文章
...NVMe SSDs,开发者正在优化GRUB对新硬件的支持,并研究如何确保在不同启动环境下MBR与GPT分区表的有效兼容。 其次,在Windows安装与部署方面,微软于今年发布了Windows 11新版操作系统,不仅引入了全新的用户界面设计,还在安装流程中融入了智能化安装选项和更快捷的驱动识别机制。此外,随着云技术和虚拟化技术的发展,Windows To Go和Azure Sphere等新型安装方式为系统部署提供了更多可能。 在网络配置方面,IPv6在全球范围内的普及速度加快,许多网络设备厂商正致力于提升产品对IPv6协议栈的支持。与此同时,Windows操作系统也在不断更新其网络功能,包括DHCPv6客户端功能增强、DNS-over-HTTPS(DoH)支持以及更完善的组播服务管理工具。此外,Windows防火墙已新增多项高级策略设置,以满足日益复杂的网络安全需求。 最后,关于Office软件中的实用技巧,Microsoft Office 365定期发布更新,提供更丰富的协作工具和智能功能,例如Excel的数据预处理和分析能力得到显著提升,Outlook则集成了更多智能邮件管理和日程安排助手。这些实时更新和新增功能有助于用户提高工作效率,应对各种办公场景挑战。 总之,随着科技不断发展,无论是操作系统的基础架构、网络配置的复杂度还是办公应用的智能化程度都在持续演进,关注行业动态和技术前沿将帮助我们更好地理解和运用文中提及的相关知识。
2023-09-10 16:27:10
270
转载
Ruby
...如果你在用Ruby搞开发的话,那肯定对并发编程挺熟悉的吧?这玩意儿就像是编程界的“多头怪兽”,能让程序同时干好多事儿,效率蹭蹭往上涨,简直太酷了!嘿,告诉你,这根魔法棒可不是那么完美无缺的,它其实也有个小缺点呢!只要你稍微一不小心,哎呀,就有可能一脚踩空,掉进坑里啦! 我曾经也经历过这样的噩梦:一个程序运行得很慢,我以为是硬件问题,结果发现是自己在并发编程上犯了错。嘿,今天咱们就来聊聊那些经常犯的小错吧!我呢,打算用一些接地气的例子,跟大家伙儿一起看看这些错误长啥样,顺便学学怎么躲开它们。毕竟谁也不想踩雷不是? --- 2. 什么是并发编程? 简单来说,并发编程就是让程序在同一时间执行多个任务。在Ruby中,我们可以用线程(Thread)来实现这一点。比如说啊,你正在倒腾一堆数据的时候,完全可以把它切成一小块一小块的,然后让每个线程去负责一块,这样一来,效率直接拉满,干活儿的速度蹭蹭往上涨! 但是,问题来了:并发编程虽然强大,但它并不是万能药。哎呀,经常会有这样的情况呢——自个儿辛辛苦苦改代码,还以为是在让程序变得更好,结果一不小心,又给它整出了新麻烦,真是“好心办坏事”的典型啊!接下来,我们来看几个具体的例子。 --- 3. 示例一 共享状态的混乱 场景描述: 假设你正在开发一个电商网站,需要统计用户的购买记录。你琢磨着干脆让多线程上阵,给这个任务提速,于是打算让每个线程各管一拨用户的活儿,分头行动效率肯定更高!看起来很合理对不对? 问题出现: 问题是,当你让多个线程共享同一个变量(比如一个全局计数器),事情就开始变得不可控了。Ruby 的线程可不是完全分开的,这就有点像几个人共用一个记事本,大家都能随便写东西上去。结果就是,这本子可能一会儿被这个写点,一会儿被那个划掉,最后你都不知道上面到底写了啥,数据就乱套了。 代码示例: ruby 错误的代码 counter = 0 threads = [] 5.times do |i| threads << Thread.new do 100_000.times { counter += 1 } end end threads.each(&:join) puts "Counter: {counter}" 分析: 这段代码看起来没什么问题,每个线程都只是简单地增加计数器。但实际情况却是,输出的结果经常不是期望的500_000,而是各种奇怪的数字。这就好比说,counter += 1 其实不是一步到位的简单操作,它得先“读一下当前的值”,再“给这个值加1”,最后再“把新的值存回去”。问题是,在这中间的每一个小动作,都可能被别的线程突然插队过来捣乱! 解决方案: 为了避免这种混乱,我们需要使用线程安全的操作,比如Mutex(互斥锁)。Mutex可以确保每次只有一个线程能够修改某个变量。 修正后的代码: ruby 正确的代码 require 'thread' counter = 0 mutex = Mutex.new threads = [] 5.times do |i| threads << Thread.new do 100_000.times do mutex.synchronize { counter += 1 } end end end threads.each(&:join) puts "Counter: {counter}" 总结: 这一段代码告诉我们,共享状态是一个雷区。如果你非要用共享变量,记得给它加上锁,不然后果不堪设想。 --- 4. 示例二 死锁的诅咒 场景描述: 有时候,我们会遇到更复杂的情况,比如两个线程互相等待对方释放资源。哎呀,这种情况就叫“死锁”,简直就像两只小猫抢一个玩具,谁都不肯让步,结果大家都卡在那里动弹不得,程序也就这样傻乎乎地停在原地,啥也干不了啦! 问题出现: 想象一下,你有两个线程,A线程需要获取锁X,B线程需要获取锁Y。想象一下,A和B两个人都想打开两把锁——A拿到了锁X,B拿到了锁Y。然后呢,A心想:“我得等B先把他的锁Y打开,我才能继续。”而B也在想:“等A先把她的锁X打开,我才能接着弄。”结果俩人就这么干等着,谁也不肯先放手,最后就成了“死锁”——就像两个人在拔河,谁都不松手,僵在那里啥也干不成。 代码示例: ruby 死锁的代码 lock_a = Mutex.new lock_b = Mutex.new thread_a = Thread.new do lock_a.synchronize do puts "Thread A acquired lock A" sleep(1) lock_b.synchronize do puts "Thread A acquired lock B" end end end thread_b = Thread.new do lock_b.synchronize do puts "Thread B acquired lock B" sleep(1) lock_a.synchronize do puts "Thread B acquired lock A" end end end thread_a.join thread_b.join 分析: 在这段代码中,两个线程都在尝试获取两个不同的锁,但由于它们的顺序不同,最终导致了死锁。运行这段代码时,你会发现程序卡住了,没有任何输出。 解决方案: 为了避免死锁,我们需要遵循“总是按照相同的顺序获取锁”的原则。比如,在上面的例子中,我们可以强制让所有线程都先获取锁A,再获取锁B。 修正后的代码: ruby 避免死锁的代码 lock_a = Mutex.new lock_b = Mutex.new thread_a = Thread.new do [lock_a, lock_b].each do |lock| lock.synchronize do puts "Thread A acquired lock {lock.object_id}" end end end thread_b = Thread.new do [lock_a, lock_b].each do |lock| lock.synchronize do puts "Thread B acquired lock {lock.object_id}" end end end thread_a.join thread_b.join 总结: 死锁就像一只隐形的手,随时可能掐住你的喉咙。记住,保持一致的锁顺序是关键! --- 5. 示例三 不恰当的线程池 场景描述: 线程池是一种管理线程的方式,它可以复用线程,减少频繁创建和销毁线程的开销。但在实际使用中,很多人会因为配置不当而导致性能下降甚至崩溃。 问题出现: 假设你创建了一个线程池,但线程池的大小设置得不合理。哎呀,这就好比做饭时锅不够大,菜都堆在那儿煮不熟,菜要是放太多呢,锅又会冒烟、潽得到处都是,最后饭也没做好。线程池也一样,太小了任务堆成山,程序半天没反应;太大了吧,电脑资源直接被榨干,啥事也干不成,还得收拾烂摊子! 代码示例: ruby 线程池的错误用法 require 'thread' pool = Concurrent::FixedThreadPool.new(2) 20.times do |i| pool.post do sleep(1) puts "Task {i} completed" end end pool.shutdown pool.wait_for_termination 分析: 在这个例子中,线程池的大小被设置为2,但有20个任务需要执行。哎呀,这就好比你请了个帮手,但他一次只能干两件事,其他事儿就得排队等着,得等前面那两件事儿干完了,才能轮到下一件呢!这种情况下,整个程序的执行时间会显著延长。 解决方案: 为了优化线程池的性能,我们需要根据系统的负载情况动态调整线程池的大小。可以使用Concurrent::CachedThreadPool,它会根据当前的任务数量自动调整线程的数量。 修正后的代码: ruby 使用缓存线程池 require 'concurrent' pool = Concurrent::CachedThreadPool.new 20.times do |i| pool.post do sleep(1) puts "Task {i} completed" end end sleep(10) 给线程池足够的时间完成任务 pool.shutdown pool.wait_for_termination 总结: 线程池就像一把双刃剑,用得好可以提升效率,用不好则会成为负担。记住,线程池的大小要根据实际情况灵活调整。 --- 6. 示例四 忽略异常的代价 场景描述: 并发编程的一个常见问题是,线程中的异常不容易被察觉。如果你没有妥善处理这些异常,程序可能会因为一个小错误而崩溃。 问题出现: 假设你有一个线程在执行某个操作时抛出了异常,但你没有捕获它,那么整个线程池可能会因此停止工作。 代码示例: ruby 忽略异常的代码 threads = [] 5.times do |i| threads << Thread.new do raise "Error in thread {i}" if i == 2 puts "Thread {i} completed" end end threads.each(&:join) 分析: 在这个例子中,当i == 2时,线程会抛出一个异常。哎呀糟糕!因为我们没抓住这个异常,程序直接就挂掉了,别的线程啥的也别想再跑了。 解决方案: 为了防止这种情况发生,我们应该在每个线程中添加异常捕获机制。比如,可以用begin-rescue-end结构来捕获异常并进行处理。 修正后的代码: ruby 捕获异常的代码 threads = [] 5.times do |i| threads << Thread.new do begin raise "Error in thread {i}" if i == 2 puts "Thread {i} completed" rescue => e puts "Thread {i} encountered an error: {e.message}" end end end threads.each(&:join) 总结: 异常就像隐藏在暗处的敌人,稍不注意就会让你措手不及。学会捕获和处理异常,是成为一个优秀的并发编程者的关键。 --- 7. 结语 好了,今天的分享就到这里啦!并发编程确实是一项强大的技能,但也需要谨慎对待。大家看看今天这个例子,是不是觉得有点隐患啊?希望能引起大家的注意,也学着怎么避开这些坑,别踩雷了! 最后,我想说的是,编程是一门艺术,也是一场冒险。每次遇到新挑战,我都觉得像打开一个神秘的盲盒,既兴奋又紧张。不过呢,光有好奇心还不够,还得有点儿耐心,就像种花一样,得一点点浇水施肥,不能急着看结果。相信只要我们不断学习、不断反思,就一定能写出更加优雅、高效的代码! 祝大家编码愉快!
2025-04-25 16:14:17
32
凌波微步
转载文章
...善,从理论研究到工程实践,各类创新技术和解决方案层出不穷,为大数据时代的数据价值挖掘奠定了坚实基础。广大读者可以通过关注最新的科研成果、行业报告和技术博客,深入了解这一领域的发展趋势和应用案例,以便更好地应对和解决实际工作中的海量数据挑战。
2024-03-01 12:40:17
541
转载
转载文章
...种新的bash插件被开发出来,可实现命令历史记录加密存储,有效防止恶意攻击者通过查看历史记录获取敏感信息。而在端口扫描防御方面,除了传统的NMAP工具之外,一些实时网络监控与入侵检测系统如Zeek (前Bro)也因其高效识别异常网络活动的能力而备受瞩目。 综上所述,随着信息技术的发展和安全威胁的变化,Linux系统的账号安全管理需不断跟进最新研究和技术动态,结合文中所述的基础措施,灵活运用先进的安全技术和管理理念,构建更加稳固的操作系统安全防线。
2023-05-07 23:37:44
95
转载
转载文章
...的影响。 2. 行业实践案例:今年年初,某大型商业银行在其年度报告中分享了运用大数据与人工智能技术优化信用卡业务的实践经验,其中重点介绍了如何通过构建多元线性回归模型及正则化方法处理信贷风险评估和客户消费潜力预测问题,这一实例为业界提供了宝贵借鉴。 3. 监管政策影响:随着数据隐私保护法规(例如欧盟GDPR、中国个人信息保护法)的出台和完善,金融机构在利用用户数据进行信用消费预测时面临更多挑战。《经济学人》杂志的一篇文章对此进行了深度解读,探讨了在严格遵守法规的前提下,如何合法合规地挖掘数据价值以提高预测准确性。 4. 数据科学工具更新:Python生态中的Pandas、Statsmodels等库不断迭代升级,为数据分析工作者提供了更为强大的功能支持。最近,Scikit-learn发布了新版更新,强化了其在回归模型诊断、正则化模型训练等方面的性能,值得广大数据科学家关注并应用于实际项目中。 综上所述,了解前沿学术研究成果、掌握行业最佳实践、关注法律法规变化以及跟踪数据科学工具更新,都将有助于深化您在信用卡消费预测领域的专业素养,并为解决实际业务问题提供有力支持。
2023-11-23 15:52:56
106
转载
转载文章
转载文章
...。Quartz 允许开发人员根据时间间隔(或天)来调度作业。它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。整合了 Quartz 的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业。虽然可以通过属性文件(在属性文件中可以指定 JDBC 事务的数据源、全局作业和/或触发器侦听器、插件、线程池,以及更多)配置 Quartz,但它根本没有与应用程序服务器的上下文或引用集成在一起。结果就是作业不能访问 Web 服务器的内部函数;例如,在使用 WebSphere 应用服务器时,由 Quartz 调度的作业并不能影响服务器的动态缓存和数据源。 二、java中实现定时任务分类 从实现的技术上来分类,目前主要有三种技术(或者说有三种产品): Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少,这篇文章将不做详细介绍。 使用Quartz,这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂,稍后会详细介绍。 Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多,稍后会介绍。 从作业类的继承方式来讲,可以分为两类: 作业类需要继承自特定的作业类基类,如Quartz中需要继承自org.springframework.scheduling.quartz.QuartzJobBean;java.util.Timer中需要继承自java.util.TimerTask。 作业类即普通的java类,不需要继承自任何基类。 注:个人推荐使用第二种方式,因为这样所以的类都是普通类,不需要事先区别对待。 从任务调度的触发时机来分,这里主要是针对作业使用的触发器,主要有以下两种: 每隔指定时间则触发一次,在Quartz中对应的触发器为:org.springframework.scheduling.quartz.SimpleTriggerBean 每到指定时间则触发一次,在Quartz中对应的调度器为:org.springframework.scheduling.quartz.CronTriggerBean 注:并非每种任务都可以使用这两种触发器,如java.util.TimerTask任务就只能使用第一种。Quartz和spring task都可以支持这两种触发条件。 三、Quartz与Spring的集成 第一种,作业类继承自特定的基类:org.springframework.scheduling.quartz.QuartzJobBean。 第一步:定义作业类 Java代码 import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; public class Job1 extends QuartzJobBean { private int timeout; private static int i = 0; //调度工厂实例化后,经过timeout时间开始执行调度 public void setTimeout(int timeout) { this.timeout = timeout; } / 要调度的具体任务 / @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { System.out.println("定时任务执行中…"); } } 第二步:spring配置文件中配置作业类JobDetailBean Xml代码 <bean name="job1" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="com.gy.Job1" /> <property name="jobDataAsMap"> <map> <entry key="timeout" value="0" /> </map> </property> </bean> 说明:org.springframework.scheduling.quartz.JobDetailBean有两个属性,jobClass属性即我们在java代码中定义的任务类,jobDataAsMap属性即该任务类中需要注入的属性值。 第三步:配置作业调度的触发方式(触发器) Quartz的作业触发器有两种,分别是 org.springframework.scheduling.quartz.SimpleTriggerBean org.springframework.scheduling.quartz.CronTriggerBean 第一种SimpleTriggerBean,只支持按照一定频度调用任务,如每隔30分钟运行一次。 配置方式如下: Xml代码 <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="job1" /> <property name="startDelay" value="0" /><!-- 调度工厂实例化后,经过0秒开始执行调度 --> <property name="repeatInterval" value="2000" /><!-- 每2秒调度一次 --> </bean> 第二种CronTriggerBean,支持到指定时间运行一次,如每天12:00运行一次等。 配置方式如下: Xml代码 <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="job1" /> <!—每天12:00运行一次 --> <property name="cronExpression" value="0 0 12 ?" /> </bean> 关于cronExpression表达式的语法参见附录。 第四步:配置调度工厂 Xml代码 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger" /> </list> </property> </bean> 说明:该参数指定的就是之前配置的触发器的名字。 第五步:启动你的应用即可,即将工程部署至tomcat或其他容器。 第二种,作业类不继承特定基类。 Spring能够支持这种方式,归功于两个类: org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean 这两个类分别对应spring支持的两种实现任务调度的方式,即前文提到到java自带的timer task方式和Quartz方式。这里我只写MethodInvokingJobDetailFactoryBean的用法,使用该类的好处是,我们的任务类不再需要继承自任何类,而是普通的pojo。 第一步:编写任务类 Java代码 public class Job2 { public void doJob2() { System.out.println("不继承QuartzJobBean方式-调度进行中..."); } } 可以看出,这就是一个普通的类,并且有一个方法。 第二步:配置作业类 Xml代码 <bean id="job2" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject"> <bean class="com.gy.Job2" /> </property> <property name="targetMethod" value="doJob2" /> <property name="concurrent" value="false" /><!-- 作业不并发调度 --> </bean> 说明:这一步是关键步骤,声明一个MethodInvokingJobDetailFactoryBean,有两个关键属性:targetObject指定任务类,targetMethod指定运行的方法。往下的步骤就与方法一相同了,为了完整,同样贴出。 第三步:配置作业调度的触发方式(触发器) Quartz的作业触发器有两种,分别是 org.springframework.scheduling.quartz.SimpleTriggerBean org.springframework.scheduling.quartz.CronTriggerBean 第一种SimpleTriggerBean,只支持按照一定频度调用任务,如每隔30分钟运行一次。 配置方式如下: Xml代码 <bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean"> <property name="jobDetail" ref="job2" /> <property name="startDelay" value="0" /><!-- 调度工厂实例化后,经过0秒开始执行调度 --> <property name="repeatInterval" value="2000" /><!-- 每2秒调度一次 --> </bean> 第二种CronTriggerBean,支持到指定时间运行一次,如每天12:00运行一次等。 配置方式如下: Xml代码 <bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="job2" /> <!—每天12:00运行一次 --> <property name="cronExpression" value="0 0 12 ?" /> </bean> 以上两种调度方式根据实际情况,任选一种即可。 第四步:配置调度工厂 Xml代码 <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="cronTrigger" /> </list> </property> </bean> 说明:该参数指定的就是之前配置的触发器的名字。 第五步:启动你的应用即可,即将工程部署至tomcat或其他容器。 到此,spring中Quartz的基本配置就介绍完了,当然了,使用之前,要导入相应的spring的包与Quartz的包,这些就不消多说了。 其实可以看出Quartz的配置看上去还是挺复杂的,没有办法,因为Quartz其实是个重量级的工具,如果我们只是想简单的执行几个简单的定时任务,有没有更简单的工具,有! 四、Spring-Task 上节介绍了在Spring 中使用Quartz,本文介绍Spring3.0以后自主开发的定时任务工具,spring task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包,而且支持注解和配置文件两种 形式,下面将分别介绍这两种方式。 第一种:配置文件方式 第一步:编写作业类 即普通的pojo,如下: Java代码 import org.springframework.stereotype.Service; @Service public class TaskJob { public void job1() { System.out.println(“任务进行中。。。”); } } 第二步:在spring配置文件头中添加命名空间及描述 Xml代码 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:task="http://www.springframework.org/schema/task" 。。。。。。 xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"> 第三步:spring配置文件中设置具体的任务 Xml代码 <task:scheduled-tasks> <task:scheduled ref="taskJob" method="job1" cron="0 ?"/> </task:scheduled-tasks> <context:component-scan base-package=" com.gy.mytask " /> 说明:ref参数指定的即任务类,method指定的即需要运行的方法,cron及cronExpression表达式,具体写法这里不介绍了,详情见上篇文章附录。 <context:component-scan base-package="com.gy.mytask" />这个配置不消多说了,spring扫描注解用的。 到这里配置就完成了,是不是很简单。 第二种:使用注解形式 也许我们不想每写一个任务类还要在xml文件中配置下,我们可以使用注解@Scheduled,我们看看源文件中该注解的定义: Java代码 @Target({java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Scheduled { public abstract String cron(); public abstract long fixedDelay(); public abstract long fixedRate(); } 可以看出该注解有三个方法或者叫参数,分别表示的意思是: cron:指定cron表达式 fixedDelay:官方文档解释:An interval-based trigger where the interval is measured from the completion time of the previous task. The time unit value is measured in milliseconds.即表示从上一个任务完成开始到下一个任务开始的间隔,单位是毫秒。 fixedRate:官方文档解释:An interval-based trigger where the interval is measured from the start time of the previous task. The time unit value is measured in milliseconds.即从上一个任务开始到下一个任务开始的间隔,单位是毫秒。 下面我来配置一下。 第一步:编写pojo Java代码 import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @Component(“taskJob”) public class TaskJob { @Scheduled(cron = "0 0 3 ?") public void job1() { System.out.println(“任务进行中。。。”); } } 第二步:添加task相关的配置: Xml代码 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd" default-lazy-init="false"> <context:annotation-config /> <!—spring扫描注解的配置 --> <context:component-scan base-package="com.gy.mytask" /> <!—开启这个配置,spring才能识别@Scheduled注解 --> <task:annotation-driven scheduler="qbScheduler" mode="proxy"/> <task:scheduler id="qbScheduler" pool-size="10"/> 说明:理论上只需要加上<task:annotation-driven />这句配置就可以了,这些参数都不是必须的。 Ok配置完毕,当然spring task还有很多参数,我就不一一解释了,具体参考xsd文档http://www.springframework.org/schema/task/spring-task-3.0.xsd。 附录: cronExpression的配置说明,具体使用以及参数请百度google 字段 允许值 允许的特殊字符 秒 0-59 , - / 分 0-59 , - / 小时 0-23 , - / 日期 1-31 , - ? / L W C 月份 1-12 或者 JAN-DEC , - / 星期 1-7 或者 SUN-SAT , - ? / L C 年(可选) 留空, 1970-2099 , - / - 区间 通配符 ? 你不想设置那个字段 下面只例出几个式子 CRON表达式 含义 "0 0 12 ?" 每天中午十二点触发 "0 15 10 ? " 每天早上10:15触发 "0 15 10 ?" 每天早上10:15触发 "0 15 10 ? " 每天早上10:15触发 "0 15 10 ? 2005" 2005年的每天早上10:15触发 "0 14 ?" 每天从下午2点开始到2点59分每分钟一次触发 "0 0/5 14 ?" 每天从下午2点开始到2:55分结束每5分钟一次触发 "0 0/5 14,18 ?" 每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发 "0 0-5 14 ?" 每天14:00至14:05每分钟一次触发 "0 10,44 14 ? 3 WED" 三月的每周三的14:10和14:44触发 "0 15 10 ? MON-FRI" 每个周一、周二、周三、周四、周五的10:15触发 Cron 表达式包括以下 7 个字段: 秒 分 小时 月内日期 月 周内日期 年(可选字段) 特殊字符 Cron 触发器利用一系列特殊字符,如下所示: 反斜线(/)字符表示增量值。例如,在秒字段中“5/15”代表从第 5 秒开始,每 15 秒一次。 问号(?)字符和字母 L 字符只有在月内日期和周内日期字段中可用。问号表示这个字段不包含具体值。所以,如果指定月内日期,可以在周内日期字段中插入“?”,表示周内日期值无关紧要。字母 L 字符是 last 的缩写。放在月内日期字段中,表示安排在当月最后一天执行。在周内日期字段中,如果“L”单独存在,就等于“7”,否则代表当月内周内日期的最后一个实例。所以“0L”表示安排在当月的最后一个星期日执行。 在月内日期字段中的字母(W)字符把执行安排在最靠近指定值的工作日。把“1W”放在月内日期字段中,表示把执行安排在当月的第一个工作日内。 井号()字符为给定月份指定具体的工作日实例。把“MON2”放在周内日期字段中,表示把任务安排在当月的第二个星期一。 星号()字符是通配字符,表示该字段可以接受任何可能的值。 字段 允许值 允许的特殊字符 秒 0-59 , - / 分 0-59 , - / 小时 0-23 , - / 日期 1-31 , - ? / L W C 月份 1-12 或者 JAN-DEC , - / 星期 1-7 或者 SUN-SAT , - ? / L C 年(可选) 留空, 1970-2099 , - / 表达式意义 "0 0 12 ?" 每天中午12点触发 "0 15 10 ? " 每天上午10:15触发 "0 15 10 ?" 每天上午10:15触发 "0 15 10 ? " 每天上午10:15触发 "0 15 10 ? 2005" 2005年的每天上午10:15触发 "0 14 ?" 在每天下午2点到下午2:59期间的每1分钟触发 "0 0/5 14 ?" 在每天下午2点到下午2:55期间的每5分钟触发 "0 0/5 14,18 ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发 "0 0-5 14 ?" 在每天下午2点到下午2:05期间的每1分钟触发 "0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发 "0 15 10 ? MON-FRI" 周一至周五的上午10:15触发 "0 15 10 15 ?" 每月15日上午10:15触发 "0 15 10 L ?" 每月最后一日的上午10:15触发 "0 15 10 ? 6L" 每月的最后一个星期五上午10:15触发 "0 15 10 ? 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发 "0 15 10 ? 63" 每月的第三个星期五上午10:15触发 每天早上6点 0 6 每两个小时 0 /2 晚上11点到早上8点之间每两个小时,早上八点 0 23-7/2,8 每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点 0 11 4 1-3 1月1日早上4点 0 4 1 1 本篇文章为转载内容。原文链接:https://zhanghaiyang.blog.csdn.net/article/details/51397459。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-10-27 18:50:19
344
转载
转载文章
...新启动计算机,在 启动画面上便增加了一个用户alanhkg888了,选alanhkg888进入www.shanpow.com_删除Download和DataStore文件夹中的所有文件。 6.登入后在控制台→使用者账户→选忘记密码的用户,然后选移除密码 7.在登入画面中选原来的用户便可不需密码情况下等入(因已移除了) 8.删除刚才新增的用户:在控制台→使用者账户→选alanhkg888,然后选移除账户便可 方法3 1、重新启动Windows XP,在启动画面出现后的瞬间按F8,选择带命令行的安全模 式运行。 2、运行过程停止时,系统列出了超级用户administrator和本地用户owner的选择菜单, 点击administrator,进入命令行模式。 3、键入命令:net user owner 123456/add,强制性将owner用户的口令更改为123456。 若想在此添加某一用户:用户名为abcdef,口令为123456的话,请输入net user abcdef 123456/add,添加后可用net localgroup administrators abcdef/add命令将用户提升为 系统管理组administrators用户,具有超级权限。 4.DOS下删windows\system32\config里面的SAM档就可以了 5.开机后按键盘的Delete键进入BIOS界面。找到User Password选项,其默认为关闭状 态。启动并输入用户密码(1~8位英文或数字)。计算机提示请再输入一遍以确认密码无误, 保存退出后重新启动机器,这时就会在开机时出现密码菜单 方法4我们知道在安装Windows XP过程中,首先是以administrator默认登录,然后会要 求创建一个新账户,以便进入Windows XP时使用此新建账户登录,而且在Windows XP的 登录接口中也只会出现创建的这个用户账号,不会出现administrator,但实际上该 administrator账号还是存在的,且密码为空。 【二】:Windows 7实战经验 Windows 7实战经验:完美解决Windows 7更新失败(Windows Update 错误 80070003) 很多用户反映,为什么Windows 7的自动更新会出显未知错误,导致很多更新都不能正确安装?针对这个问题,在我对自己的Windows 7进行更新的时候,有时也会发生类似的问题,经过研究,已经完美解决,下面给大家解决方案! 如果在检查更新时收到Windows Update错误80070003,则需要删除Windows用于标识计算机更新的临时文件。若要删除临时文件,请停止Windows Update服务,删除临时更新文件,重新启动Windows Update服务,然后再次尝试检查Windows更新。 以下步骤为解决Windows 7更新错误方法,本博客亲测有效。 必须以管理员身份进行登录,才能执行这些步骤。 1.单击打开“管理工具(通过单击“开始”按钮,再依次单击“控制面板”,然后单击“管理工具”。 2.双击“服务”。如果系统提示您输入管理员密码或进行确认,请键入该密码或提供确认。 3.单击“名称”列标题以逆序排列名称。找到“Windows Update”服务,右键单击该服务,然后单击“停止”。 1.打开“计算机”。 2.双击安装Windows的本地硬盘(通常是驱动器C)。 3.双击Windows文件夹,然后双击SoftwareDistribution文件夹。 4.双击打开DataStore文件夹,然后删除该文件夹中的所有文件。如果系统提示您输入管理员密码或进行确认,请键入该密码或提供确认。 5.单击“后退”按钮。在SoftwareDistribution文件夹中,双击打开Download文件夹,删除该文件夹中的所有文件,然后关闭窗口。如果系统提示您输入管理员密码或进行确认,请键入该密码或提供确认。 必须以管理员身份进行登录,才能执行这些步骤。 1.单击打开“管理工具(方法同上)”。 2.双击“服务”。如果系统提示您输入管理员密码或进行确认,请键入该密码或提供确认。 3.单击“名称”列标题以逆序排列名称。找到“Windows Update”服务,右键单击该服务,然后单击“启动”。 4.关闭“服务”窗口和“管理工具”窗口。 完成上面操作,你需要重新更新看看可以成功更新了吗,一般因为我们删除了自动更新的一些文件,如果你仔细观察的话,那些文件大小并不是很小,所以我们再更新的时候等待的时间可能会长一些! 【三】:Win10系统提示“无法完成更新正在撤销更改” 更新win10系统补丁之后,系统会提示“window10无法更新,正在撤销”,需要重启好几次,这该怎么办呢?下面小编就向大家介绍一下windows10系统无法完成更新正在撤销更改的解决方法,欢迎大家参考和学习。 系统更新失败,反复重启还是不行,那是不是下载下来的补丁没用了呢??所以我们先要删除Windows更新的缓存文件!在做以下操作之前,首先我们要确认系统内的windows update & BITS服务设置是否开启。 检查方法: 1、按“Win+R”组合键打开运行,输入“services.msc”,点击确定(如果弹出用户账户控制窗口,我们点击“继续”)。 2、双击打开“Background Intelligent Transfer Services”服务。 3、在选项卡点击“常规”,要保证“启动类型”是“自动”或者“手动”。然后点击“服务状态”“启用”按钮。 4. 重复步骤3分别对“Windows Installer”,“Cryptographic Services”, “software licensing service” 以及“Windows Update”这四项服务进行检查。 解决办法: 1、按“Windows+X”打开“命令提示符(管理员)”。 2、输入“net stop wuauserv”回车(我们先把更新服务停止)。 3、输入”%windir%\SoftwareDistribution“回车(删除Download和DataStore文件夹中的所有文件)。 4、最后输入“net start wuauserv”回车(重新开启系统更新服务)。 完成以上的步骤之后,我们就可以在“Windows Update”中再次尝试检查更新即可。 以上就是windows10系统无法完成更新正在撤销更改的解决方法介绍了。遇到同样问题的用户,可以尝试一下这个方法,如果不行,可以留言,小编会继续寻找其他的解决办法。 【四】:Windows更新失败提示错误码80070003怎么办 Windows7,Windows8.1,Windows10在更新过程中,所更新的程序无法安装,导致更新失败,提示错误码80070003。遇到这种情况,无论再试一次,或重启电脑,更新程序仍无法安装,出现错误码80070003提示。关于这个故障,下面小编就为大家介绍一下具体的解决方法吧,欢迎大家参考和学习。 具体解决方法步骤: 1、在电脑更新过程中,更新失败,程序无法安装,出现错误码80070003的提示。如图1 2、打开控制面板,点击“系统和安全”,打开对话框。如图2 3、在打开的对话框中,点击“管理工具”-双击“服务”,在打开的对话框的下方找到“Windows Update"。(如图3),选择Windows Update,点击界面左上角的”停止“按键,或是单击右键选择”停止“。(如图4),以管理员身份进入,如果提示需要输入秘码,则输入秘码。 4、在C盘,打开”Windows"文件夹,-双击打开“SoftwareDistribution"文件夹,找到下面的2个文件夹。打开”DataStore"文件夹,删除里面所有的文件。反回上一步。如图5.1,再打开"Download"文件夹,删除里面所有的文件。(如图5.2) 5、返回第三步的操作,选择Windows Update,右键单击,选择“启动”。 6、做完上面操作后,安装更新文件就会顺利了。 本篇文章为转载内容。原文链接:https://blog.csdn.net/weixin_42620202/article/details/119158423。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-02-16 16:18:33
136
转载
转载文章
...绪论 1 1.1系统开发背景 1 1,2研究现状 1 1.3研究主要内容 3 2相关技术 5 2.1 SSM的技术原理 5 2.1.1 SSM语言及其特点 5 2.1.2 Java及Java Servlets概述 6 2.1.3 JavaBean简介 6 2.2 服务器配置 7 2.2.1 Tomcat安装及配置 8 2.2.2 数据库配置 8 3系统分析 11 3.1 可行性分析 11 3.1.1 技术可行性 11 3.1.2 操作可行性 11 3.1.3 经济可行性 11 3.1.4 法律可行性 11 3.2 腕表交易系统功能需求分析 11 3.3 数据库需求分析 12 4系统设计 13 4.1 系统功能模块设计 13 4.2系统流程设计 13 4.2.1 系统开发流程 13 4.2.2 用户登录流程 14 4.2.3 系统操作流程 15 4.2.4 添加信息流程 15 4.2.5 修改信息流程 16 4.2.6 删除信息流程 16 4.3系统用例分析 17 4.3.1 管理员用例图 17 4.3.2 用户用例图 18 4.4 数据库设计 19 4.4.1 tb_Ware(商品信息表) 19 4.4.2 tb_manager(管理员信息表) 19 4.4.3 tb_sub(订单生成表) 19 4.4.4 tb_Link(超级链接表) 20 4.4.5 tb_Affiche(公告信息表) 20 4.3 用SSM连接数据库 20 5系统实现 22 5.1 前台部分 22 5.1.1 前台总体框架 22 5.1.2 商城首页 22 5.1.3 产品详情页 23 5.1.4 评价 23 5.2 后台部分 24 5.2.1 后台主页 24 5.2.2 后台评价管理 25 5.2.3 商品管理 25 5.2.4 商品修改 26 5.2.5 分类管理 26 5.2.6 订单管理 27 5.2.7 腕表购物车管理 27 6系统测试 28 6.1系统测试的意义 28 6.2性能测试 29 6.3测试分析 29 总 结 30 致 谢 31 参考文献 31 3系统分析 3.1 可行性分析 腕表交易系统主要目标是实现网上展示腕表交易系统信息,购买腕表产品。在确定了目标后,我们从以下四方面对能否实现本系统目标进行可行性分析。 3.1.1 技术可行性 腕表交易系统主要采用Java技术,基于B/S结构,MYSQL数据库,主要包括前端应用程序的开发以及后台数据库的建立和维护两个方面。对于应用程序的开发要求具备功能要完备、使用应简单等特点,而对于数据库的建立和维护则要求建立一个数据完整性强、数据安全性好、数据稳定性高的库。腕表交易系统的开发技术具有很高可行性,且开发人员掌握了一定的开发技术,所以系统的开发具有可行性。 3.1.2 操作可行性 腕表交易系统的登录界面简单易于操作,采用常见的界面窗口来登录界面,通过电脑进行访问操作,会员只要平时使用过电脑都能进行访问操作。此系统的开发采用PHP语言开发,基于B/S结构,这些开发环境使系统更加完善。本系统具有易操作、易管理、交互性好的特点,在操作上是非常简单的。因此本系统可以进行开发。 3.1.3 经济可行性 腕表交易系统是基于B/S模式,采用MYSQL数据库储存数据,所要求的硬件和软件环境,市场上都很容易购买,程序开发主要是管理系统的开发和维护。所以程序在开发人力、财力上要求不高,而且此系统不是很复杂,开发周期短,在经济方面具有较高的可行性。 3.1.4 法律可行性 此腕表交易系统是自己设计的管理系统,具有很大的实际意义。开发环境软件和使用的数据库都是开源代码,因此对这个系统进行开发与普通的系统软件设计存在很大不同,没有侵权等问题,在法律上完全具有可行性。 综上所述,腕表交易系统在技术、经济、操作和法律上都具有很高的可行性,开发此程序是很必要的。 3.2 腕表交易系统功能需求分析 此基于SSM的腕表交易系统分前台功能和后台功能: 1)前台部分由用户使用,主要包括用户注册,腕表购物车管理,订单管理,个人资料管理,留言板管理 2)后台部分由管理员使用,主要包括管理员身份验证,商品管理,处理订单,用户信息管理,连接信息管理 3.3 数据库需求分析 数据库的设计通常是以一个已经存在的数据库管理系统为基础的,常用的数据库管理系统有MYSQL,SQL,Oracle等。我采用了Mysql数据库管理系统,建立的数据库名为db_business。 整个系统功能需要以下数据项: 用户:用户id、用户名称、登录密码、用户真实姓名、性别、邮箱地址、联系地址、联系电话、密码问题、答案、注册时间。 留言:主题id、作者姓名、Email、主题名称、留言内容、发布时间。 商品:商品id、名称、价格、图片路径、类型、简要介绍、存储地址、上传人姓名、发布时间、是否推荐。 订单:订单号、用户名、真实姓名、订购日期、Email、地址、邮编、付款方式、联系方式、运送方式、订单核对、其他。 管理员:管理员id、管理员名称、管理员密码。 公告:公告内容、公告时间。 4系统设计 4.1 系统功能模块设计 功能结构图如下: 图9 功能模块设计图 从图中可以看出,网上腕表交易系统可以分为前台和后台两个部分,前台部分由用户使用,主要包括用户注册,生成订单,腕表购物车管理,查看腕表购物车,查看留言,订购产品,订单查询和发布留言7个模块;本文转载自http://www.biyezuopin.vip/onews.asp?id=11975后台部分由管理员使用,主要包括管理员身份验证,商品管理,处理订单,用户信息管理,连接信息管理5个模块。 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><base href="<%=basePath%>"/><title>腕表商城</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><meta name="viewport" content="width=device-width, initial-scale=1"><!-- Favicon --><link rel="shortcut icon" type="image/x-icon" href="img/favicon.png"><link rel="stylesheet" type="text/css" href="<%=basePath%>home/css/font-awesome.min.css" /><link rel="stylesheet" type="text/css" href="<%=basePath%>home/css/bootstrap.css" /><link rel="stylesheet" type="text/css" href="<%=basePath%>home/css/style.css"><link rel="stylesheet" type="text/css" href="<%=basePath%>home/css/magnific-popup.css"><link rel="stylesheet" type="text/css" href="<%=basePath%>home/css/owl.carousel.css"><script type="text/javascript">function getprofenlei(){ var html = ""; $.ajax({url: "leixing.action?list&page=0&rows=30",type: "POST",async: false, contentType: "application/x-www-form-urlencoded;charset=UTF-8",success: function (data) { $.each(data.rows, function (i, val) { html += ' <li ><a href="home/search.jsp?fenlei='+val.id+'" >'+val.a1+' </a></li>';})} }); $("fenlei").html(html);}function gettop1(){var html = "";$.ajax({url: "leixing.action?list&page=0&rows=10",type: "POST",async: false,success: function (data) {var total='';//<div class="tab-pane active" id="nArrivals">// <div class="nArrivals owl-carousel" id="top1">$.each(data.rows, function (i, valmm) { html+='<div class="nArrivals owl-carousel" id="'+valmm.id+'">';$.ajax({url: "shangpin.action?list&page=0&rows=10",type: "POST",async: false,data: { fenlei:valmm.id },success: function (data) { $.each(data.rows, function (i, val) { html+='<div class="product-grid">'+'<div class="item">'+' <div class="product-thumb">'+' <div class="image product-imageblock"> <a href="home/details.jsp?ids='+val.id+'"> <img data-name="product_image" style="width:223px;height:285px;" src="<%=basePath%>'+val.tupian1+'" alt="iPod Classic" title="iPod Classic" class="img-responsive"> <img style="width:223px;height:285px;" src="<%=basePath%>'+val.tupian1+'" alt="iPod Classic" title="iPod Classic" class="img-responsive"> </a> </div>'+' <div class="caption product-detail text-left">'+' <h6 data-name="product_name" class="product-name mt_20"><a href="home/details.jsp?ids='+val.id+'" title="Casual Shirt With Ruffle Hem">'+val.biaoti+'</a></h6>'+' <div class="rating"> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-1x"></i></span> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-1x"></i></span> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-1x"></i></span> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-1x"></i></span> <span class="fa fa-stack"><i class="fa fa-star-o fa-stack-1x"></i><i class="fa fa-star fa-stack-x"></i></span> </div>'+'<span class="price"><span class="amount"><span class="currencySymbol">$</span>'+val.jiage+'</span>'+'</span>'+'<div class="button-group text-center">'+' <div class="wishlist"><a href="home/details.jsp?ids='+val.id+'"><span>wishlist</span></a></div>'+'<div class="quickview"><a href="home/details.jsp?ids='+val.id+'"><span>Quick View</span></a></div>'+'<div class="compare"><a href="home/details.jsp?ids='+val.id+'"><span>Compare</span></a></div>'+'<div class="add-to-cart"><a href="home/details.jsp?ids='+val.id+'"><span>Add to cart</span></a></div>'+'</div>'+'</div>'+'</div>'+'</div>'+' </div>'; })html+='</div>'; } })}) $("nArrivals").html(html); } }); 本篇文章为转载内容。原文链接:https://blog.csdn.net/newlw/article/details/127608579。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-03-21 18:24:50
66
转载
转载文章
...境中的复杂安全隐患而开发的技术。 业完成所需的转型,因而难以支持在混合云中运行云原生应用。要转而部署混合云环境,第一步要做的就是摆脱专有虚拟化。 红帽虚拟化包含 sVirt 和安全增强型 Linux(SELinux),是红帽企业 Linux 专为检测和预防当前 IT 环境中的复杂安全隐患而开发的技术。 借助红帽虚拟化,你可以尽享开源虚拟机监控程序的所有优势,还能获得企业级技术支持、更新和补丁,使你的环境保持最新状态,持续安心运行。开源和 RESTful API,以及 Microsoft Windows 的认证,可帮你实现跨平台的互操作性。提供的 API 和软件开发工具包(SDK)则有助于将我们的解决方案扩展至你现有和首选管理工具,并提供相关支持。 本篇文章为转载内容。原文链接:https://blog.csdn.net/qq_34799070/article/details/107900861。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-04-06 08:58:59
121
转载
转载文章
...识基础,积极参与科研实践,提高论文发表与竞赛获奖的含金量。此外,合理定位自身并积极拓宽信息获取渠道,了解心仪高校与导师的研究方向及团队氛围,同样至关重要。 综上所述,保研不仅是对过往学业成果的检验,更是对未来学术生涯的前瞻布局。广大有志于深造的学子需紧跟政策导向,全面提升自我,才能在这场无声的竞争中脱颖而出,成功走向理想的学术殿堂。
2023-05-02 23:03:36
120
转载
转载文章
...分阶段建设,工控程序开发通常面临对接多种PLC厂商设备和不同系列与型号。因此出现了一种专门与不同PLC通讯的软件协议-OPC(OLE for Process Control),而各厂家在OPC基础上进行了不同程度的扩展,为了应对标准化和跨平台的趋势,和了更好的推广OPC,OPC基金会近些年在之前OPC成功应用的基础上推出了一个新的OPC标准-OPC UA。处于通讯效率上的考虑,很多厂家生产了OPCUA设备模块,内置处理器,性价比不错。不过这不是本文关注的重点。 概念 OPC UA(OPC Unified Architecture)是指OPC统一体系架构,是一种基于服务的、跨越平台的解决方案。 特点 扩展了OPC的应用平台。传统的基于COM/DCOM 的OPC技术只能基于Windows操作系统,OPC UA支持拓展到Linux和Unix平台。这使得基于OPC UA的标准产品可以更好地实现工厂级的数据采集和管理; 不再基于DCOM通讯,不需要进行DCOM安全设置; OPC UA定义了统一数据和服务模型,使数据组织更为灵活,可以实现报警与事件、数据存取、历史数据存取、控制命令、复杂数据的交互通信; OPC UA比OPC DA更安全。OPC UA传递的数据是可以加密的,并对通信连接和数据本身都可以实现安全控制。新的安全模型保证了数据从原始设备到MES,ERP系统,从本地到远程的各级自动化和信息化系统的可靠传递; OPC UA可以穿越防火墙,实现Internet 通讯。 依赖 我们通常不会从头写,可以基于OpcUa.core.dll库和OpcUa.Client.dll库,而且附上这2个库的源代码。 配置OpcUA Server 您可以安装任何一款支持OPCUA的服务端软件进行以下配置(此为示例配置,您可根据你的实际情况进行配置) 1、OpcUa Server Url:opc.tcp://192.168.100.1:4840。 2、OpcUa EndPoint:[UaServer@cMT-EAB9] [None] [None] [opc.tcp://192.168.100.1:4840/G01] 3、PLC Device Name:Siemens S7-1200/S7-1500 4、Account:user1 5、Password:自己设置 6、在PLC中开了2个数据块,分别为DB4长度110个字、DB5长度122个字。 7、对应第4块创建标签,第一个名称为DB4.0-99,地址为DB4DBW0.100,数据类型为Short,长度100,即定义长度最长为100的Short数组。第二个名称为DB4.100-109,地址为DB4DBW100.10,数据类型为Short,方便快速读取。 5、对应第5块创建3个标签,第一个名称为DB5.0-99,地址为DB5DBW0.100,数据类型为Short,第二个名称为DB5.100-121, 地址为DB5DBW100.22,数据类型为Short,即定义长度最长为100的Short数组。方便快速读取。第三个标签名称为DB5DBW64,地址为DB5DBW64,数据类型为Short。 具体如下图: 关键代码 using System;using System.Collections.Generic;using System.Linq;using Opc.Ua.Helper;using Mesnac.Equips;namespace Mesnac.Equip.OPC.OpcUa.OPCUA{public class Equip : BaseEquip{region 字段定义private bool _isOpen = false; //是否已打开设备private bool _isClosing = false; //是否正在关闭设备private OPCUAClass myOpcHelper; //OPCUA设备访问辅助对象private Dictionary<string, string> dicTags = null; //保存标签集合private Dictionary<string, object> readResult = null; //设备标签数据缓存private int stepLen = 250; //标签变量的步长设置private string groupNamePrefix = "DB"; //数据块号前缀private string childTagFlag = "~"; //子元素标签标志符private System.Threading.Thread innerReadThread = null; //内部读取线程对象private int innerReadRate = 1000; //内部读取频率endregionregion 属性定义/// <summary>/// OPCUA Server Url/// </summary>public string OpcUaServerUrl{get{//return (this.Main.ConnType as Mesnac.Equips.Connection.OPCUA.ConnType).OpcUaServerUrl;return "opc.tcp://192.168.1.102:4840";//return "opc.tcp://192.168.100.1:4840";//return "opc.tcp://192.168.100.2:4840";} }/// <summary>/// 要连接的OPCUA服务器上的服务名/// </summary>public string OpcUaServiceName{get{//return (this.Main.ConnType as Mesnac.Equips.Connection.OPCUA.ConnType).OpcUaServiceName;return "[UaServer@cMT-9F1F] [None] [None] [opc.tcp://192.168.1.102:4840/G01]";//return "[UaServer@cMT-EAB9] [None] [None] [opc.tcp://192.168.100.1:4840/G01]";//return "[UaServer@cMT-EA5B] [None] [None] [opc.tcp://192.168.100.2:4840/G02]";//return "[UaServer@cMT-EA5B] [None] [None] [opc.tcp://192.168.100.2:4840/G01]";} }/// <summary>/// 要连接的OPCUA服务器上指定服务名下的PLC的名称/// </summary>public string PLCName{get{//return (this.Main.ConnType as Mesnac.Equips.Connection.OPCUA.ConnType).PLCName;//return "Feeding";return "Siemens_192.168.2.1";//return "Rockwell_192.168.1.10";} }/// <summary>/// OPCUA服务器的访问账户/// </summary>public string Account{get{//return (this.Main.ConnType as Mesnac.Equips.Connection.OPCUA.ConnType).Account;return "user1";} }/// <summary>/// OPCUA服务器的访问密码/// </summary>public string Password{get{//return (this.Main.ConnType as Mesnac.Equips.Connection.OPCUA.ConnType).Password;return "1";} }endregionregion BaseEquip成员实现/// <summary>/// 打开连接设备/// </summary>/// <returns>成功返回true,失败返回false</returns>public override bool Open(){lock (this){this._isClosing = false;if (this._isOpen == true && this.myOpcHelper != null){return true;}this.State = false;this.myOpcHelper = new OPCUAClass();this.dicTags = this.myOpcHelper.ConnectOPCUA(this.OpcUaServerUrl, this.Account, this.Password, this.OpcUaServiceName, this.PLCName); //连接OPCServerif (this.dicTags == null || this.dicTags.Count == 0){this.myOpcHelper = null;Console.WriteLine("OPC连接失败!");this.State = false;return false;}else{this.State = true;this._isOpen = true;region 初始化读取结果this.readResult = new Dictionary<string, object>();foreach (Equips.BaseInfo.Group group in this.Group.Values){if (!group.IsAutoRead){continue;}int groupMinStart = group.Start;int groupMaxEnd = group.Start + group.Len;int groupMaxLen = group.Len;foreach (Equips.BaseInfo.Group g in this.Group.Values){if (!g.IsAutoRead){continue;}if (g.Block == group.Block){if (g.Start < group.Start){groupMinStart = g.Start;}if (g.Start + g.Len > groupMaxEnd){groupMaxEnd = g.Start + g.Len;} }}groupMaxLen = groupMaxEnd - groupMinStart;int tagCount = groupMaxLen % this.stepLen == 0 ? groupMaxLen / this.stepLen : groupMaxLen / this.stepLen + 1;int currLen = 0;for (int i = 0; i < tagCount; i++){string tagName = String.Empty;if (tagCount == 1){tagName = String.Format("{0}-{1}", groupMinStart, groupMinStart + groupMaxLen - 1);currLen = groupMaxLen;}else if (i == tagCount - 1){tagName = String.Format("{0}-{1}", groupMinStart + (i this.stepLen), groupMinStart + (i this.stepLen) + (groupMaxLen % this.stepLen == 0 ? this.stepLen : groupMaxLen % this.stepLen) - 1);currLen = groupMaxLen % this.stepLen;}else{tagName = String.Format("{0}-{1}", groupMinStart + (i this.stepLen), groupMinStart + (i this.stepLen) + this.stepLen - 1);currLen = this.stepLen;}string tagFullName = String.Format("{0}{1}.{2}", groupNamePrefix, group.Block, tagName);if (!this.readResult.ContainsKey(tagFullName)){bool exists = false;region 判断读取结果标签组的范围是否包括了此标签 比如tagFullName DB5.220-299,在readResult中存在 DB5.200-299,则认为已存在,不需要再添加string[] beginend = null;int begin = 0;int end = 0;string[] startstop = tagFullName.Replace(String.Format("{0}{1}.", groupNamePrefix, group.Block), String.Empty).Split(new char[] { '-' });int start = 0;int stop = 0;bool parseResult = false;if (startstop.Length == 2){parseResult = int.TryParse(startstop[0], out start);if (parseResult){parseResult = int.TryParse(startstop[1], out stop);} }if (parseResult){int existsMinBegin = 0; //已存在标签的最小开始索引int existsMaxEnd = 0; //已存在标签的最大结束索引bool isContinue = true; //标签值是否连续string[] existsTags = this.readResult.Keys.ToArray<string>();foreach (string tag in existsTags){if (tag.StartsWith(String.Format("{0}{1}.", groupNamePrefix, group.Block)) && tag.Contains(".") && tag.Contains("-")){string[] tagname = tag.Split(new char[] { '.' });if (tagname.Length == 2){beginend = tagname[1].Split(new char[] { '-' });if (beginend.Length == 2){parseResult = int.TryParse(beginend[0], out begin);if (parseResult){parseResult = int.TryParse(beginend[1], out end);}region 计算最小开始索引和最大结束索引if (begin < existsMinBegin){existsMinBegin = begin;region 判断标签值是否连续if (existsMaxEnd != 0 && begin != existsMaxEnd + 1){isContinue = false;}endregion}if (end > existsMaxEnd){existsMaxEnd = end;}endregion} }if (parseResult){if (start >= begin && stop <= end){exists = true;break;}if (isContinue){if (start >= existsMinBegin && stop <= existsMaxEnd){exists = true;break;} }} }} }endregionif (!exists){ushort[] groupData = new ushort[currLen];this.readResult[tagFullName] = groupData;Console.WriteLine(tagFullName);} }}//int tagCount = group.Len % this.stepLen == 0 ? group.Len / this.stepLen : group.Len / this.stepLen + 1;//int currLen = 0;//for (int i = 0; i < tagCount; i++)//{// string tagName = String.Empty;// if (tagCount == 1)// {// tagName = String.Format("{0}-{1}", group.Start, group.Start + group.Len - 1);// currLen = group.Len;// }// else if (i == tagCount - 1)// {// tagName = String.Format("{0}-{1}", group.Start + (i this.stepLen), group.Start + (i this.stepLen) + (group.Len % this.stepLen == 0 ? this.stepLen : group.Len % this.stepLen) - 1);// currLen = group.Len % this.stepLen;// }// else// {// tagName = String.Format("{0}-{1}", group.Start + (i this.stepLen), group.Start + (i this.stepLen) + this.stepLen - 1);// currLen = this.stepLen;// }// string tagFullName = String.Format("{0}{1}.{2}", groupNamePrefix, group.Block, tagName);// if (!this.readResult.ContainsKey(tagFullName))// {// short[] groupData = new short[currLen];// this.readResult[tagFullName] = groupData;// }//} }endregionregion 开启内部定时读取if (this.innerReadThread == null){this.innerReadRate = this.Main.ReadHz / 2;this.innerReadThread = new System.Threading.Thread(this.InnerAutoRead);this.innerReadThread.Start();}endregion}return this.State;} }/// <summary>/// 从设备读取数据/// </summary>/// <param name="block">要读取的块号</param>/// <param name="start">要读取的起始字</param>/// <param name="len">要读取的长度</param>/// <param name="buff">读取成功后的输出数据</param>/// <returns>成功返回true,失败返回false</returns>public override bool Read(string block, int start, int len, out object[] buff){lock (this){buff = null;if (this._isClosing){return false;}string readstrflag = String.Format("{0}{1}.{2}-{3}", this.groupNamePrefix, block, start, start + len - 1);System.Text.StringBuilder sbtaglength = new System.Text.StringBuilder();string startTag = String.Empty;string groupName = String.Format("{0}{1}", this.groupNamePrefix, block); //要读取的OPCServer块List<ushort> groupData = new List<ushort>();List<string> groupTagNames = new List<string>();int startIndex = 0;try{if (!Open()){return false;}//return true;string[] keys = this.readResult.Keys.ToArray<string>();foreach (string key in keys){if (key.StartsWith(groupName) && key.Replace(String.Format("{0}.", groupName), String.Empty).Contains("-")){groupTagNames.Add(key);} }groupTagNames.Sort(); //对块标签进行排序foreach (string key in groupTagNames){if (String.IsNullOrEmpty(startTag)){startTag = key.Replace(String.Format("{0}.", groupName), String.Empty);}ushort[] values;if (this.readResult[key] is ushort[]){values = this.readResult[key] as ushort[];}else{values = new ushort[] { (ushort)this.readResult[key] };}sbtaglength.Append(String.Format("tagName={0}, buff length = {1}", key, values.Length));groupData.AddRange(values);}buff = new object[len];if (!String.IsNullOrEmpty(startTag)){string strStartIndex = startTag.Substring(0, startTag.IndexOf("-"));int.TryParse(strStartIndex, out startIndex);startIndex = start - startIndex;Array.Copy(groupData.ToArray(), startIndex, buff, 0, buff.Length);}else{}return true;}catch (Exception ex){Console.WriteLine(String.Join(";", groupTagNames.ToArray<string>()));Console.WriteLine("data length = " + groupData.Count);Console.WriteLine(this.Name + "读取失败[" + readstrflag + "]:" + ex.Message);Console.WriteLine(sbtaglength.ToString());this.State = false;return false;} }}/// <summary>/// 写入数据到设备/// </summary>/// <param name="block">要写入的块号</param>/// <param name="start">要写入的起始字</param>/// <param name="buff">要写如的数据</param>/// <returns>成功返回true,失败返回false</returns>public override bool Write(int block, int start, object[] buff){bool result = true;lock (this){try{if (this._isClosing){return false;}if (!Open()){return false;}bool isWrite = false;region 按标签变量写入string itemId = "";foreach (Equips.BaseInfo.Group group in this.Group.Values){if (group.Block == block.ToString()){foreach (Equips.BaseInfo.Data data in group.Data.Values){if (group.Start + data.Start == start && data.Len == buff.Length){if (this.dicTags.ContainsKey(data.Name)){itemId = this.dicTags[data.Name];}break;} }} }if (!String.IsNullOrEmpty(itemId)){UInt16[] intBuff = new UInt16[buff.Length];for (int i = 0; i < intBuff.Length; i++){intBuff[i] = 0;if (!UInt16.TryParse(buff[i].ToString(), out intBuff[i])){Console.WriteLine("在写入OPCUA标签时把buff中的元素转为UInt16类型失败!");} }result = this.myOpcHelper.WriteUInt16(itemId, intBuff);if (!result){Console.WriteLine(String.Format("标签变量[{0}]写入失败!", itemId));return false;}else{Console.WriteLine("按标签变量写入..." + itemId);isWrite = true;} }if (isWrite){return true;}endregionregion 按块写入region 先读取相应标签数数据string startTag = String.Empty;string groupName = String.Format("{0}{1}", this.groupNamePrefix, block); //要读取的OPCServer块List<ushort> groupData = new List<ushort>();string[] keys = readResult.Keys.Where(o => o.StartsWith(groupName) && o.Contains("-")).OrderBy(c => c).ToArray<string>();foreach (string key in keys){if (String.IsNullOrEmpty(startTag)){startTag = key.Replace(String.Format("{0}.", groupName), String.Empty);}string[] beginEnd = key.Replace(String.Format("{0}.", groupName), String.Empty).Split(new char[] { '-' });if (beginEnd.Length != 2){Console.WriteLine(String.Format("标签变量[{0}]未按约定方式命名,请按[DB块号].[起始字-结束字]方式标签变量进行命名!", String.Format("{0}.{1}", key)));return false;}int begin = 0;int end = 0;int.TryParse(beginEnd[0], out begin);int.TryParse(beginEnd[1], out end);region 写入之前,先读取一下PLC的值if ((start >= begin && start <= end) || ((start + buff.Length - 1) >= begin && (start + buff.Length - 1) <= end) || (start < begin && (start + buff.Length - 1) > end)){this.ReadTag(key);if (this.readResult.ContainsKey(key) && this.readResult[key] is Array){Console.WriteLine("read = " + key);groupData.AddRange(this.readResult[key] as ushort[]);}else{Console.WriteLine(String.Format("读取结果中不包含标签变量[{0}]的值!", String.Format("{0}", key)));} }else{if (this.readResult.ContainsKey(key) && this.readResult[key] is Array){Console.WriteLine("no read = " + key);groupData.AddRange(this.readResult[key] as ushort[]);} }endregion}endregionif (String.IsNullOrEmpty(startTag)){Console.WriteLine("写入失败,未在OPCUAserver中找到对应的标签,block = {0}, start = {1}, len = {2}", block, start, buff.Length);return false;}region 更新标签中对应的数据后,再写回OPCServerint startIndex = 0;string strStartIndex = startTag.Substring(0, startTag.IndexOf("-"));int.TryParse(strStartIndex, out startIndex);startIndex = start - startIndex;ushort[] newDataBuffer = groupData.ToArray();for (int i = 0; i < buff.Length; i++){ushort svalue = 0;ushort.TryParse(buff[i].ToString(), out svalue);newDataBuffer[startIndex + i] = svalue;}int index = 0;string[] keys2 = readResult.Keys.Where(o => o.StartsWith(groupName) && o.Contains("-")).OrderBy(c => c).ToArray<string>();foreach (string key2 in keys2){string[] beginEnd = key2.Replace(String.Format("{0}.", groupName), String.Empty).Split(new char[] { '-' });if (beginEnd.Length != 2){Console.WriteLine(String.Format("标签变量[{0}]未按约定方式命名,请按[DB块号].[起始字-结束字]方式标签变量进行命名!", String.Format("{0}", key2)));return false;}int begin = 0;int end = 0;int.TryParse(beginEnd[0], out begin);int.TryParse(beginEnd[1], out end);if ((start >= begin && start <= end) || ((start + buff.Length - 1) >= begin && (start + buff.Length - 1) <= end) || (start < begin && (start + buff.Length - 1) > end)){//Console.WriteLine("---------------------------------------------------------");//Console.WriteLine("start = " + start);//Console.WriteLine("start + buff.Length - 1 = " + (start + buff.Length -1));//Console.WriteLine("begin = " + begin);//Console.WriteLine("end = " + end);//Console.WriteLine("---------------------------------------------------------");if (!this.dicTags.ContainsKey(key2)){Console.WriteLine(String.Format("写入失败:标签变量[{0}]在OpcUA Server中未定义!", String.Format("{0}", key2)));return false;}int len = (this.readResult[key2] as ushort[]).Length;ushort[] tagDataBuff = new ushort[len];//Console.WriteLine("newDataBuff");//Console.WriteLine(String.Join(",", newDataBuffer));//Console.WriteLine("index = " + index);//Console.WriteLine("tagDataBuff.Length = " + tagDataBuff.Length);//Array.Copy(newDataBuffer, begin, tagDataBuff, 0, tagDataBuff.Length);int existsMinBegin = this.GetExistsMinBeginByBlock(block.ToString());Array.Copy(newDataBuffer, begin - existsMinBegin, tagDataBuff, 0, tagDataBuff.Length);index += tagDataBuff.Length;//Console.WriteLine("Write " + key2);//Console.WriteLine(String.Join(",", tagDataBuff));//Console.WriteLine("写入标签:" + this.dicTags[key2]);result = this.myOpcHelper.WriteUInt16(this.dicTags[key2], tagDataBuff);if (!result){Console.WriteLine(String.Format("向标签变量[{0}]中写入值失败!", String.Format("{0}", key2)));return false;}else{this.ReadTag(key2);Console.WriteLine("写入...");}//Console.WriteLine("---------------------------------------------------------");} }endregionendregionreturn result;}catch (Exception ex){Console.WriteLine(this.Name + "写入失败:" + ex.Message);return false;} }}/// <summary>/// 关闭方法,断开与设备的连接释放资源/// </summary>public override void Close(){try{this._isClosing = true;System.Threading.Thread.Sleep(this.Main.ReadHz);if (this.innerReadThread != null){this.innerReadThread.Abort();this.innerReadThread = null;} }catch (Exception ex){Console.WriteLine("关闭内部读取OPCUA线程异常:" + ex.Message);}try{if (this.myOpcHelper != null){this.myOpcHelper.Close();this.myOpcHelper = null;this.State = false;this._isOpen = false;} }catch (Exception ex){Console.WriteLine("关于与OPCUA服务连接异常:" + ex.Message);} }endregionregion 辅助方法/// <summary>/// 获取某个数据块标签的最小开始索引/// </summary>/// <param name="block">块号</param>/// <returns>返回数据块标签的最小开始索引</returns>private int GetExistsMinBeginByBlock(string block){int existsMinBegin = 99999; //已存在标签的最小开始索引int existsMaxEnd = 0; //已存在标签的最大结束索引bool isContinue = true; //标签值是否连续string[] existsTags = this.readResult.Keys.ToArray<string>();string[] beginend = null;bool parseResult = false;int begin = 0;int end = 0;foreach (string tag in existsTags){if (tag.StartsWith(String.Format("{0}{1}.", groupNamePrefix, block)) && tag.Contains(".") && tag.Contains("-")){string[] tagname = tag.Split(new char[] { '.' });if (tagname.Length == 2){beginend = tagname[1].Split(new char[] { '-' });if (beginend.Length == 2){parseResult = int.TryParse(beginend[0], out begin);if (parseResult){parseResult = int.TryParse(beginend[1], out end);}region 计算最小开始索引和最大结束索引if (begin < existsMinBegin){existsMinBegin = begin;region 判断标签值是否连续if (existsMaxEnd != 0 && begin != existsMaxEnd + 1){isContinue = false;}endregion}if (end > existsMaxEnd){existsMaxEnd = end;}endregion} }if (parseResult){//} }}return existsMinBegin;}/// <summary>/// 读取标签/// </summary>/// <param name="tagName"></param>private void ReadTag(string tagName){UInt16[] buff = null;if (this.dicTags.ContainsKey(tagName)){if (this.myOpcHelper.ReadUInt16(this.dicTags[tagName], out buff)){//Console.WriteLine("tagName={0}, buff length = {1}", tagName, buff.Length);if (this.readResult.ContainsKey(tagName)){this.readResult[tagName] = buff;}else{this.readResult.Add(tagName, buff);} }else{Console.WriteLine("Mesnac.Equip.OPC.OpcUa.OPCUA.Equip.ReadTag Exception 读取标签:[{0}]失败!", tagName);} }else{Console.WriteLine("Mesnac.Equip.OPC.OpcUa.OPCUA.Equip.ReadTag Exception OPCUA Server中未定义此标签:[{0}]!", tagName);} }/// <summary>/// 内部自动读取方法/// </summary>private void InnerAutoRead(){while (this._isOpen && this._isClosing == false){try{if (this.myOpcHelper == null){this._isClosing = true;this.State = false;return;}lock (this){string[] keys = this.readResult.Keys.ToArray<string>();foreach (string key in keys){this.ReadTag(key);} }System.Threading.Thread.Sleep(this.innerReadRate);}catch (Exception ex){Console.WriteLine("Mesnac.Equip.OPC.OpcUa.OPCUA.Equip.InnerAutoRead Exception : " + ex.Message);} }this.innerReadThread = null;}endregionregion 析构方法~Equip(){this.Close();}endregion} } 代码下载 代码下载 本篇文章为转载内容。原文链接:https://blog.csdn.net/zlbdmm/article/details/96714776。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-05-10 18:43:00
269
转载
转载文章
...优化展开了深入研究与实践。 例如,Linux 5.11版本引入了eBPF(Extended Berkeley Packet Filter)的重大改进,使得XDP(eXpress Data Path)能够更高效地处理网络数据包,进一步缩短数据路径,减少系统开销。同时,eBPF也被广泛应用于追踪分析、流量控制等高级功能,为解决大规模并发问题提供了全新的思路。 此外,硬件技术也在不断跟进以适应高并发需求。Intel推出的第三代至强可扩展处理器中包含了对DPDK(Data Plane Development Kit)的深度优化支持,通过集成高性能网卡与CPU间的智能加速引擎,有效提升了数据包处理效率,降低了延迟。 而在软件层面,Google开源的gVisor项目提供了一种轻量级的用户态沙箱容器运行时环境,它能显著降低上下文切换带来的开销,对于解决大规模并发连接挑战具有积极意义。 综上所述,面对日益增长的并发连接挑战,无论是操作系统内核的底层优化,还是硬件技术的革新升级,以及创新的软件解决方案,都在合力推动着现代数据中心向更高并发、更低延迟的目标迈进。对于技术人员来说,紧跟这些发展趋势并将其应用到实际工作中,将有助于构建更加稳定、高效的大型分布式系统。
2023-04-11 18:25:52
260
转载
转载文章
...,存在很多运营后台的开发需求。每次开发一个后台都得有人力去投入。 后来我就在老大的所开发的一套 PHP 框架的基础上进行改进。实现了只要指定一张 Mysql 数据库中的表,就可以自动生成 bootstrap 样式的管理后台界面。支持列表展示、搜索、删除、批量删除、文本框、时间控件等等一切基础功能。再以后涉及管理后台的功能,只需要在这个基础上改造就行了,人力投入降低了很多,风格也得到了统一。这个工具现在在我们团队内部仍然还在广泛地使用。 还有个故事我也讲过,就是老大分配给我一个图片下载的任务。我不局限于完成完成任务,而且还把文件系统、磁盘工作原理都深入整理了一遍,就是这篇《Linux文件系统十问》 03 转战搜狗 2013 下半年的时候,我第一次感受到了工作岗位的震荡。我还专注解决某一个 bug,花了不少精力都还没查到 bug 的原因。这时候,部门助理突然招呼我们所有人都下楼,在银科腾讯的 Image 印象店集合。在那里,见到了腾讯的总裁 Martin。这还是第一次离大老板只有一米远的距离。 所有人都是一脸困惑,突然把大家召集下来是干嘛呢。原来就在几个小时前,腾讯总办已经和搜狗达成了协议。腾讯收购搜狗的一部分股份,并把我们连人带业务一起注入到了搜狗。 没想到,是老板用一种更牛逼的方式帮我把 bug 给解决了。 14 年 1 月正式到了搜狗以后,我们没有继续做搜索了。而是内部 Transfer 到了另外一个部门。做起了搜狗网址导航、搜狗手机助手、搜狗浏览器等业务。我也是从那个时间点,开始带团队的,也是从那以后慢慢开始从个人贡献者到带团队集体输出的角色的转变。 在搜狗工作的这 7 年的时间里,我仍然也是延续之前的风格。不拘泥于完成工作中的产品需求,以及老大交付的任务。而是主动去探索各种项目中有价值的事情。 比如在手机助手的推广中,我琢磨了新用户的安装流程的各个环节后,找出影响用户安装率提升的关键因素。然后对新版本安装包采用了多种技术方案,将单用户获取成本削减了20%+,这一年下来就是千万级别的成本节约。 我们还主动在手机助手的搜索模块中应用了简单的学习算法。采用了用户协同,标签相似,点击反馈等方法将手机助手的搜索转化率提升了数个百分点。 除了用技术提升业务以外,我还结合工作中的问题进行了很多的深度技术思考。 如有一次我们自己维护了一个线上的redis(当时工程部还没有redis平台,redis服务要业务自己维护)。为了优化性能,我把后端的请求由短连接改成了长连接。虽然看效果性能确实是优化了,但是我的思考并没有停止。我们所有的后端机都会连接这个redis。这样在这个redis实例上可能得有6000多条并发连接存在。我就开始疑惑,Linux 最多能有多少个TCP连接呢,我这 6000 条长连接会不会把这个服务器玩坏? 再比如,我们组的服务器遭遇过几次连接相关的线上问题。其中一次是因为端口紧张而导致 CPU 消耗飙升。后来我又深入研究了一下。 最近,由于 Docker 的广泛应用。底层的网络工作方式已经在悄悄地发生变化了。所以我又开辟了一个网络虚拟化的坑,来一点一点地填。 现在我们的「开发内功修炼」公众号和 Github 就是在作为一个我和大家分享我的技术思考的一个窗口。 04 重回腾讯 时隔 7 年,我又以一种奇特的方式变回了腾讯人的身份。 腾讯再一次收购了搜狗的股份,这一次不再是控股,而是全资。 在离开腾讯的这 7 年多的时间里,腾讯的内部技术工作方式已经发生了翻天覆地的变化。 所以在刚转回腾讯的这一段时间里,我花了大量的精力来熟悉腾讯基于 tRPC 的各种技术生态。除了工作日,也投入了不少周末的精力。 05 再叨叨几句 最后,水文里挤干货,通过我今天的文章我想给大家分享这么几点经验。 第一,是要学会抬头看路,选择一个好的赛道进去。我非常庆幸我当年从广电赛道切换到了互联网,获得了更大的舞台。不过其实我自己在这点上做的也不是特别好,2013年底入职搜狗前拒绝了字节大把期权的offer,要不然我我早就财务自由了。 第二,不要光被动接收领导的指令干活。要主动积极思考项目中哪些地方是待改进的,想到了你就去做。领导都非常喜欢积极主动的员工。我自己也是喜欢招一些能主动思考,积极推进的同学。这些人能创造意外的价值。 第三,工作中除了业务以外还要主动技术的深度思考。毕竟技术仍然是开发的立命之本。在晋升考核的时候,业务数据做的再好也代替不了技术实力的核心位置。把工作中的技术点总结一下,在公司内分享出来。不涉及机密的话在外网分享一下更好。对你自己,对你的团队,都是好事。 技术交流群 最近有很多人问,有没有读者交流群,想知道怎么加入。 最近我创建了一些群,大家可以加入。交流群都是免费的,只需要大家加入之后不要随便发广告,多多交流技术就好了。 目前创建了多个交流群,全国交流群、北上广杭深等各地区交流群、面试交流群、资源共享群等。 有兴趣入群的同学,可长按扫描下方二维码,一定要备注:全国 Or 城市 Or 面试 Or 资源,根据格式备注,可更快被通过且邀请进群。 ▲长按扫描 往期推荐 武大94年博士年薪201万入职华为!学霸日程表曝光,简直降维打击! 腾讯三面:40亿个QQ号码如何去重? 我被开除了。。只因为看了骂公司的帖子 如果你喜欢本文, 请长按二维码,关注 Hollis. 转发至朋友圈,是对我最大的支持。 点个 在看 喜欢是一种感觉 在看是一种支持 ↘↘↘ 本篇文章为转载内容。原文链接:https://blog.csdn.net/hollis_chuang/article/details/121738393。 该文由互联网用户投稿提供,文中观点代表作者本人意见,并不代表本站的立场。 作为信息平台,本站仅提供文章转载服务,并不拥有其所有权,也不对文章内容的真实性、准确性和合法性承担责任。 如发现本文存在侵权、违法、违规或事实不符的情况,请及时联系我们,我们将第一时间进行核实并删除相应内容。
2023-02-06 11:38:24
232
转载
站内搜索
用于搜索本网站内部文章,支持栏目切换。
知识学习
实践的时候请根据实际情况谨慎操作。
随机学习一条linux命令:
netstat -tulpn
- 查看网络连接状态、监听的TCP/UDP端口及其对应进程信息。
推荐内容
推荐本栏目内的其它文章,看看还有哪些文章让你感兴趣。
2023-04-28
2023-08-09
2023-06-18
2023-04-14
2023-02-18
2023-04-17
2024-01-11
2023-10-03
2023-09-09
2023-06-13
2023-08-07
2023-03-11
历史内容
快速导航到对应月份的历史文章列表。
随便看看
拉到页底了吧,随便看看还有哪些文章你可能感兴趣。
时光飞逝
"流光容易把人抛,红了樱桃,绿了芭蕉。"