首页 文章 精选 留言 我的

精选列表

搜索[编写],共10000篇文章
优秀的个人博客,低调大师

用木兰语言编写文字冒险游戏(十三、四章),又一个特性发现

继续改写 Python 文字冒险游戏,第十三章的主要添加了玩家在每格的行动限制: func 选择命令(位置, 玩家) { 行动 = nil while !行动 { 可选行动 = 取可选行动(位置, 玩家) 选择 = input("行动: ") 行动 = 可选行动.get(选择) if 行动 { // 为避免如此特殊处理, 其他行动也需加"环境"参数 if (行动 == 玩家.攻击) { 行动(位置.敌人) } else { 行动() } } else { println("选择无效!") } } } 另外地图改成表示如下,连同对应解析方法: 地图描述 = "| |VT| |\n" + "| |EN| |\n" + "|EN|ST|EN|\n" + "| |EN| |\n" 十四章又添加了一个商贩角色,可以购买装备。另外,将地图解析方法改进为可以读取起始位置: func 解析地图描述 { if !检查无误(地图描述) { throw SyntaxError("描述 is invalid!") } 各行 = 地图描述.splitlines() 各行 = list(filter(x -> x, 各行)) for y, 行 in enumerate(各行) { 行数据 = [] 各块 = 行.split("|") 各块 = list(filter(c -> c, 各块)) for x, 块 in enumerate(各块) { 地块类型 = 地块类型表[块] if 地块类型 == 起始位置 { extern 起始点 起始点 = tuple(x, y) } 行数据.append(地块类型 ? 地块类型(x, y) : nil) } 地图.append(行数据) } } 木兰语言相关注意点 ? : 是表达式,不能单独作为声明使用。因此 print( 2<4 ? 3 : 4) 这样可以,if 2>1{ 2<4 ? print(3) : print(4) } 就不可以。 python 的 global 对应木兰的 extern,发现在引用时有个奇特之处。简化演示如下: 如下声明 x,函数 a 对其作修改: x = 1 func a() { extern x x = x * 3 } println("原值:`x`") 如果这样引用: using * in 原值 a() println("修改后:`x`") 输出如下,可见修改未果: 原值:1 修改后:1 这样调用才修改有效: using 原值 原值.a() println("修改后:`原值.x`") 输出: 原值:1 修改后:3 Python 行为也相同。待研究,不知是否与之前发现的 引用机制 有何关联。

优秀的个人博客,低调大师

教你用C语言编写万年历,程序员超乎你的想象!

学了C语言的小编闲来无事就想搞点事情做,发现可以用C语言做万年历,计算器,俄罗斯方块儿游戏之类的,就从万年历开始玩耍啦。 Step 1. 新建一个程序 制作一个应用当然必不可少的就是新建程序啦,小编这里使用的是VC6.0,记住新建的一定要是文件里的C++ Source File Step 2. 输入所需的变量 输入月,年等变量是为了在后续循环时方便进行,变量也是C语言中比较常见的一种用法。 Step 3. 输入年份和月份 要查询某年某月某日是星期几就先要输入年份和月份。 Step 4. 计算某年某月第一天的星期 当知道某年某月第一天的星期时就相当于大功告成了,接下来就是利用循环不断进行输出填满万年历。 Step 5. 调试程序 当把一个程序写完后就要进行编译,组建,都没有问题后就要开始执行啦。 执行出来的结果就如图啦,有没有觉得C语言很神奇呢。 Step 6. 关闭工作区间 别以为程序执行OK就完了哦,最后还要关闭工作区间以防程序丢失,随时养成一个良好的习惯。

优秀的个人博客,低调大师

Objective-C学习笔记(三)——用Objective-C编写第一个程序:Hello,World!

不管是哪一个程序猿,或者是学习哪一门计算机语言。写的第一个程序基本上就是Hello World。 今天我们用OC来实现第一个程序:Hello World。 在Xcode中选择新建一个项目,在对话框中选择OS X,下方选择Application, 右側选择Command line tool,表示使用的是命令行程序,点击Next;在下一个对话框中输入项目名称。并选择开发语言,能够看到在这里能够选择Swift。OC。C++。C语言。最后就是选择工作空间文件夹,直接点击Create就能够创建项目了。 创建项目完毕后,打开main.m文件,发现已经自己主动生成下面代码: #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!"); } return 0; } 哈哈,看来要打印的Hello,World!代码系统已经帮我们写好了。直接点击左上角的执行button,发现已经在控制台输出了:Hello。World!如图所看到的: 。 OC的第一个程序就这样写完了,不须要我们写一行代码。哈哈。 本文转自mfrbuaa博客园博客,原文链接:http://www.cnblogs.com/mfrbuaa/p/5418279.html,如需转载请自行联系原作者

优秀的个人博客,低调大师

从零用Rust编写正反向代理,细说HTTP行为中的几种定时器

wmproxy wmproxy已用Rust实现http/https代理, socks5代理, 反向代理, 静态文件服务器,四层TCP/UDP转发,内网穿透,后续将实现websocket代理等,会将实现过程分享出来,感兴趣的可以一起造个轮子 项目地址 国内: https://gitee.com/tickbh/wmproxy github: https://github.com/tickbh/wmproxy 敏感的时间 现实生活中大家都对时间有着概念,比如“快上班了,要不然要迟到了。”、“这班怎么这么久,怎么还没下班?”、“啊?已经晚上12点啦,等我这把游戏玩完。”、“叮叮叮,起床闹钟一直在催着你起床了。” 闹钟、自然变化、生物钟为我们提供着时间的保证。而计算机的世界里,就靠着硬件定时器,控制着时间的流逝,如果哪一天本地时间和别人的时间不一致了,此时需要找别人对时,这也就是经典的网络时间协议(NTP)。 现实的生活中,通常以分钟或者小时乃至天去和别人约定时间,而在计算机的世界里,在我们看来那就是朝生暮死的蚍蜉一般,他们生命较短,所以对他们来说,通常用s或者ms来乃至μs做通知,所以需要严格的遵守时间约定,绝对不允许有赖床的行为。 HTTP行为中的定时器 HTTP/HTTPS/WebSocket的访问撑起了互联网总流量的半臂江山,日常接触中APP或者游戏这种对外服务的基本上均是通过HTTP及HTTPS进行服务,长链接由于兼容小程序这类的大部分游戏直接也从普通的Socket转为WebSocket直接做全网的兼容。WebSocket的基础协议是由HTTP升级而来,所以也归于HTTP协议。 主要有以下列行为定时器 连接超时定时器 读操作超时定时器 写操作超时定时器 读/写操作超时定时器(在规则的时间内同时完成读和写) keep-alive超时定时器(连接保持的最长时间) 定时器类的定义 相关的超时数据均存放在该类里,接下来类型进行相应的处理 #[derive(Debug)] pub struct TimeoutLayer { pub connect_timeout: Option<Duration>, pub read_timeout: Option<Duration>, pub write_timeout: Option<Duration>, pub timeout: Option<Duration>, /// keep alive 超时时长 pub ka_timeout: Option<Duration>, read_timeout_sleep: Option<Pin<Box<Sleep>>>, write_timeout_sleep: Option<Pin<Box<Sleep>>>, timeout_sleep: Option<Pin<Box<Sleep>>>, ka_timeout_sleep: Option<Pin<Box<Sleep>>>, } 连接超时定时器 此时约定的是客户端向服务端请求TCP连接建立的最长时间,如果没有约定,将由系统连接超时的或者确认不可达的时候才返回失败。 如果没有连接超时,那么以下我们的型业务场景模拟: 在弱网的环境下,比如手机信号不好的地方,一次连接请求建立可能会花费10秒左右才能返回,那么如果我们没有连接超时,用户在等待了8秒,客户端的界面都没有办法给出任何的响应,就会认为服务端出现了问题或者频繁的重启客户端应用不断的进行重试而得不到预期的反馈。在App设计中,对这种情况的用户体验极差,需要在指定的时间内给用户反馈出当前网络无法访问。 客户端的设计模型中,如果有定时请求或者埋点数据之类,如果没有超时机制,容易出现短时间内打开的socket过多出现资源耗尽的情况,其次客户端不知道是否将数据已经进行发送,不确认是否需要将该条数据进行缓存以便下一次推送。 在设计模型中,连接超时必不可少,因为各种业务场景的不同,需要要不同的时间内得到预期的反馈。以下是连接超时在Rust中的实现,因为只存在于客户端主动连接服务端,所以连接超时只在客户端实现。 async fn inner_connect<A: ToSocketAddrs>(&self, addr: A) -> ProtResult<TcpStream> { if self.inner.timeout.is_some() { // 获取是否配置了连接超时, 如果有连接超时那么指定timeout if let Some(connect) = &self.inner.timeout.as_ref().unwrap().connect_timeout { match tokio::time::timeout(*connect, TcpStream::connect(addr)).await { Ok(v) => { return Ok(v?) } Err(_) => return Err(ProtError::Extension("connect timeout")), } } } let tcp = TcpStream::connect(addr).await?; Ok(tcp) } 通过指定超时时间来对连接的建立监听。 读操作超时定时器 大部分HTTP请求,只有得到完整的数据才能进行处理,少部分如文件上传这种可以边上传边操作,而是否能开始操作关系到请求的响应时间。 读超时大概有以下的可能: 服务器处理请求的时间太长,导致客户端等待超时。 服务器返回的数据量过大,导致客户端读取数据的时间超过了规定的时间。 网络延迟或网络不稳定,导致客户端无法在规定的时间内读取完数据。 这造成客户端无法及时处理数据,可以报错好让客户端换备用线路或者备用服务器等以便及时的处理数据。 读操作我们不管服务端或者客户端,不管http/1.1或者http/2均由is_read_end字段来判定,在未读完当前请求的数据前,判断是否超时。 pub fn poll_ready( &mut self, cx: &mut Context<'_>, ready_time: Instant, is_read_end: bool, is_write_end: bool, is_idle: bool, ) -> ProtResult<()> { let now = Instant::now(); if !is_read_end { if let Some(read) = &self.read_timeout { let next = ready_time + *read; if now >= next { return Err(crate::ProtError::Extension("read timeout")); } if self.read_timeout_sleep.is_some() { self.read_timeout_sleep.as_mut().unwrap().as_mut().set(tokio::time::sleep_until(next.into())); } else { self.read_timeout_sleep = Some(Box::pin(tokio::time::sleep_until(next.into()))); } let _ = Pin::new(self.read_timeout_sleep.as_mut().unwrap()).poll(cx); } } Ok(()) } 其中比较复杂的是如何判断is_read_end,因为需要区分服务端客户端或者是http/1.1及http/2,这个源码实现 http2核心,http1.1核心 写操作超时定时器 对于客户端的写,就是将请求发送到服务端,而服务端的写,刚好是将返回发送给客户端。这是数据处理的重要的一环。 在异步的处理socket中,都会将socket设置成非阻塞,也就是nonblocking,此时我们会得到一个默认的内核缓冲区大小。如果在该缓冲区未满前,我们写入数据将是0等待,该缓冲区的数据将由系统进行数据发送给另一端。 如果对方不将我们的缓冲区数据读走,那么我们此时是无法在写入到该缓冲区的,如果远程端不读,我们的传输速度将会无限的接近于0KB/S。 此时如果是服务端,有数千上万个这种该连接,每分钟只读走几个字节的数据,那么没有写入操作,我们将要保持上万的空闲连接,而默认的端口连接数为65535,那么客户端将会耗尽我们的服务资源。此种为 <font color=green>[慢速攻击]</font>。 该操作是通过is_write_end来判断是否写入完成。监听方式和读的一致,核心代码在 timeout,此处不再赘述 读/写操作超时定时器 该定时器是由读和写需要共同来完成的,在很多场景中,我们只关心该请求需要耗时多少时间来完成,此时我们不关心是读的时间或者写的时间,所以此时表示请求完成的需要在这个时间下完成 就比如HTTP/1.1中的Slow headers,也就是慢速头攻击。正常来说,我们的http/1.1的头类似如下: GET / HTTP/1.1\r\n Host : wm-proxy.com\r\n Connection: keep-alive\r\n Keep-Alive: 900\r\n Content-Length: 100000000\r\n Content_Type: application/x-www-form-urlencoded\r\n Accept: *.*\r\n \r\n 整个报文的结束将有一个空白的\r\n,如果没有收到该标记,服务端无法得到完整的头信息,也无法正确的把数据转成Request,那么此时客户端可以占用了大量的连接,从而使服务端拒绝服务。 此定时器判断由is_read_end及is_write_end有一方为false,监听方法略。 keep-alive操作超时定时器 在http/1.1中,端口是可以复用的,从而减少socket的反复建立关闭,并可以一定程度上快速的响应,这是端口请求完成后,又没有后续的请求,此时当前socket线路为空闲,即当前空闲线路的保持时间。 keep-alive为保持连接,此参数用的好可以极大的加速服务的访问,此参数设置不好的时候,如设置成9999s,那么客户端将会保持当前的空闲socket很久,从而另一个程度上造成了拒绝服务了。 此判定由is_idle来判定,判断当前是否空闲,也就是上一个请求已经读写均已完成,后一个请求还未进来,此时就为空闲时间。监听方法雷同,略。 测试客户端 let url = "http://www.baidu.com"; let req = Request::builder().method("GET").header(HeaderName::ACCEPT_ENCODING, "gzip").url(url).body("").unwrap(); Instant::now()); let client = Client::builder() // 是否支持HTTP2 // .http2(false) // 是否仅使用HTTP2 .http2_only(true) // 连接使时时间3秒 .connect_timeout(Duration::new(5, 0)) // 设置keep-alive时间10秒 .ka_timeout(Duration::new(10, 0)) // 设置读超时5秒 // .read_timeout(Duration::new(5, 0)) // 设置写超时5秒 .write_timeout(Duration::new(5, 0)) .connect(url).await.unwrap(); //发起请求 let (mut recv, sender) = client.send2(req.into_type()).await?; //接收请求 let mut res = recv.recv().await.unwrap(); //接收所有body数据 res.body_mut().wait_all().await; 测试服务端 let mut server = Server::new(stream, Some(addr)); // 设置读操作5秒 server.set_read_timeout(Some(Duration::new(5, 0))); // 设置写超时5秒 server.set_write_timeout(Some(Duration::new(5, 0))); // 设置读写超时5秒 server.set_timeout(Some(Duration::new(5, 0))); async fn operate(req: Request<RecvStream>) -> ProtResult<Response<String>> { let response = Response::builder() .version(req.version().clone()) .body("Hello World\r\n".to_string())?; Ok(response) } let _ = server.incoming(operate).await; 结语 时间的尺度越小,那么对时间的敏感度越高,定时器是约束,也是保护,保护不受攻击。感谢定时器给我们构建一个更加稳定的互联网世界。 点击 <font color=green>[关注]</font>,<font color=green>[在看]</font>,<font color=green>[点赞]</font> 是对作者最大的支持

优秀的个人博客,低调大师

WPL/s v1.3.0发布 - 支持链接卡片 - 让你在 VS Code 中编写发布知乎专栏文章

WPL/s 是一个 VS Code 插件,允许你在 VS Code 中用 Markdown 写知乎文章。最新版支持知乎链接卡片。 链接卡片格式如下 [![zhihu-link-card:本项目 GitHub 主页](./pics/vs-code-extension-search-zhihu.png)](https://github.com/jks-liu/WPL-s) 语法上和一个图片链接一样,但图片的文字需要以zhihu-link-card:开头。知乎链接卡片的外观如下:

优秀的个人博客,低调大师

python自动化测试开发利器ulipad最佳实践(可写python测试代码也可编写selenium、Appium等)

介绍 UliPad是一个国人开发的python轻量级编辑器,导向和灵活的编程器。它如类浏览器,代码自动完成许多功能,如:HTML查看器,目录浏览器,向导等。 下载与安装 下载地址:https://pypi.python.org/pypi/UliPad 安装,傻瓜式,一路next即可 配置 安装好之后双击启动之后逐步进行下面的配置。 1、文件>目录浏览,这样我们可以在左侧看到目录方便管理脚本,最终效果图如下: 2、编辑>参数>python>设置python解释器>增加>选择你本地安装python的路径下的pythonw.exe,并把描述字段填上任意名字,保存即可,最终效果图如下: PS:我这里用的是python3哦 3、进入ulipad安装目录下的conf中,如果想配置python的模板可以修改template.python这个文件,比如我这里优化为了如下,这样你每次建立新的py文件时都可以显示了。 PS:模板里的注释暂时不支持中文,会有乱码 4、你还可以设置字体等格式,这个看个人需要了,很简单,如下图: 5、对于窗口的布局可以在菜单“窗口”中调整,这个自己试一下就明白啦 6、还可以安装一些插件,非常简单,按照下图操作即可,完全傻瓜式的 使用 点击新建文件图标下的python,就可以创建一个py文件了,然后输入代码内容,之后按F5即可运行,在下方的console中可以看到结果了,效果如下

优秀的个人博客,低调大师

项目实战_Python.编写一个高性能可扩展支持自定义的插件式监控系统?

项目简介: 说明: 主要用于集中化业务主动监控,支持任意自定义PY检测插件,适用于测试/正式环境业务联调检测,后端采用Python实现,具体实现代码请阅读代码. 项目思路: 项目结构: xmzoomeye-agent ├──app │├──conf ││├──default.ini ││├──__init__.py ││└──logging.ini │├──core ││├──__init__.py ││├──__init__.pyc ││├──main.py ││└──main.pyc │├──__init__.py │├──__init__.pyc │├──libs ││├──daemonize.py ││├──daemonize.pyc ││├──__init__.py ││├──__init__.pyc ││├──runutils.py ││└──runutils.pyc │├──plugins ││├──__init__.py ││├──__init__.pyc │└──tests │└──__init__.py ├──bin │├──__init__.py │├──restart_service.sh │├──start_service.sh │└──stop_service.sh ├──ChangeLog.txt ├──docs │├──default.ini │├──designidea ││├──mindmap.png ││└──notepad.txt │├──__init__.py │└──logging.ini ├──LICENSE.txt ├──logs │├──xmzoomeye-agent-error.log │├──xmzoomeye-agent-info.log │└──xmzoomeye-agent.pid ├──README ├──requirements.txt ├──restart_service.sh ├──setup.py ├──start_service.sh ├──stop_service.sh └──xmzoomeye-agent xmzoomeye-alert ├──app │├──conf ││├──default.ini ││├──__init__.py ││└──logging.ini │├──core ││├──__init__.py ││├──__init__.pyc ││├──main.py ││└──main.pyc │├──__init__.py │├──__init__.pyc │└──libs │├──alarm ││├──api.py ││├──__init__.py ││├──__init__.pyc ││├──mail.py ││├──sms.py ││└──weixin.py │├──daemonize.py │├──daemonize.pyc │├──__init__.py │├──__init__.pyc │├──runutils.py │└──runutils.pyc ├──bin │├──__init__.py │├──restart_service.sh │├──start_service.sh │└──stop_service.sh ├──ChangeLog.txt ├──docs │├──default.ini │├──designidea ││├──mindmap.png ││└──notepad.txt │├──__init__.py │└──logging.ini ├──LICENSE.txt ├──logs │├──xmzoomeye-alert-error.log │├──xmzoomeye-alert-info.log │└──xmzoomeye-alert.pid ├──README ├──requirements.txt ├──restart_service.sh ├──setup.py ├──start_service.sh ├──stop_service.sh └──xmzoomeye-alert 项目地址: xmzoomeye_agent: https://github.com/xmdevops/xmzoomeye_agent xmzoomeye_alert: xmzoomeye_alert: https://github.com/xmdevops/xmzoomeye_alert

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

Oracle

Oracle

Oracle Database,又名Oracle RDBMS,或简称Oracle。是甲骨文公司的一款关系数据库管理系统。它是在数据库领域一直处于领先地位的产品。可以说Oracle数据库系统是目前世界上流行的关系数据库管理系统,系统可移植性好、使用方便、功能强,适用于各类大、中、小、微机环境。它是一种高效率、可靠性好的、适应高吞吐量的数据库方案。

Eclipse

Eclipse

Eclipse 是一个开放源代码的、基于Java的可扩展开发平台。就其本身而言,它只是一个框架和一组服务,用于通过插件组件构建开发环境。幸运的是,Eclipse 附带了一个标准的插件集,包括Java开发工具(Java Development Kit,JDK)。

JDK

JDK

JDK是 Java 语言的软件开发工具包,主要用于移动设备、嵌入式设备上的java应用程序。JDK是整个java开发的核心,它包含了JAVA的运行环境(JVM+Java系统类库)和JAVA工具。