CSAPP第二章-信息的表示与处理-随手记

仅作为学习《深入理解计算机系统》第二章时的笔记,仅记录对自己有启发的部分,不作为知识整理。(直接看电子书就可以了)。 因为这本书知识点非常多,所以我会抽时间多次阅读,本文也会经常更新。 原码和反码会有两个0:正0和负0 原码:用第一个位来表示正负,后面的位来表示数的大小 反码:用一个正数取反来表示这个正数的相反数 这两种表示法都会存在两个0:+0和-0。 而使用补码就只有一个0了。 补码表示的新理解 关于补码,为了计算某个正数的相反数,可以用过取反+1的方式计算得到负数的补码表示。但是还有另一种方式能够更好的理解补码。 如果用5位来表示一个数: 下标 4 3 2 1 0 代表的十进制数 每个下标的数值 -16 8 4 2 1 二进制数1 0 1 1 0 1 13 二进制数2 1 1 1 0 1 -3 二进制数3 1 1 1 1 1 -1 二进制数3 0 1 1 1 1 15 可以看到其实如果按照补码的逻辑,当使用5个位来存储数字时,最高位第5位作为符号位,它的数值为-16,其他第1到4位的数值为1、2、4、8,然后再对二进制数的各个位,乘以其对应的数值,再累加,就能得到十进制数的大小。 比如二进制数1,其十进制数=0*(-16) + 1*8 + 1*4 + 0*2 + 1*1 = 13。 而负数二进制2,其十进制数=1*(-16) + 1*8 + 1*4 + 0*2 + 1*1 = -3。...

May 5, 2022 · 3 min · JohnathanLin

Linux C++ Socket实战

本文主要介绍Linux C++ 基础Socket网络编程。 大部分知识来自于网站:https://www.geeksforgeeks.org/socket-programming-cc/ Socket编程状态图 从图中可以看到,服务端这边需要处理四步才能进入等待连接的状态,而客户端只要两步。 Socket编程中各函数简单解析 本解析仅为自己理解所用,可能有些纰漏,有则改之。 原文中的知识总结得比我更好,尽量参考原文,我的理解仅做辅助之用。 服务端 先说服务端。服务端需要指定好端口并监听,所以需要bind()绑定好端口,需要listen()进入监听状态,然后通过accept()阻塞等待客户端的消息。 引用表: #include <sys/socket> socket() setsockopt() bind() listen() accept() #include <netinet/in.h> struct sockaddr_in #include <unistd.h> read() #include <arpa/inet.h> inet_pton() socket() 这个函数是用来创建一个socket,3个参数中,需要特别传的就是前两个。返回一个socket编号,是个int值。 int sockfd = socket(domain, type, protocol) domain: IPV4 用 AF_INET, IPV6 用 AF_INET6 type: TCP 用 SOCK_STREAM, UDP 用 SOCK_UGRAM setsockopt() 这个函数用来给上面那个socket()函数返回的socket设置属性,作为服务端,为了方便? 可以设置重用地址和端口号。...

April 30, 2022 · 2 min · JohnathanLin

传统软件服务器与游戏服务器架构区别

项目 智能客服 爬虫 SLG游戏 语言 java python kotlin 模型 异步事件驱动 可能没什么模型可言 actor模型 传输协议 http http tcp + netty 传输结构 json json protobuf 数据库 oracle,redis mongodb mysql,redis 数据库框架 mybatis python库(类似jdbc) hibernate 缓存架构 管理员登录状态用redis 可能只缓存了页码 所有游戏用的数据全部缓存,每隔一段时间写到数据库中 配置信息 只有application.properties config.ini zookeeper,启动前需要将策划表信息刷到zk 并发 无并发(所以根本没用到锁) python多线程同时爬多个网站 无并发actor模型保证一次只做一件事 热更 直接重启 无 继承某个类的某个方法,替换掉线上的类 架构一览 智能客服服务端整体架构 SLG游戏整体架构 典型案例 智能客服聊天 graph LR A[客户端]-->|http聊天消息|B[智能客服系统]-->|将聊天信息放入mq|C[智能问答模型]-->|问答信息记录|D[Oracle数据库] SLG游戏士兵出征 graph LR A[客户端]-->|tcp发送的protobuf|B[Gate的Netty解包]-->|actor内部消息转发|C[WorldActor校验外城沙盘各种状态]-->|actor内部消息转发|D[playerActor内城校验和获取buff] 其中worldActor和playerActor都通过读取内存的方式读取到需要的数据,并不直接读取mysql数据库。 内存里的数据每隔一段时间(30秒左右)将变化的数据通过hibernate的方法更新到mysql中。...

April 16, 2022 · 1 min · JohnathanLin

独立个人项目开发心得 - 任务切分、挑战性、实用性和半途而废

在写文章前容许我啰嗦一下:对于软件开发,我走了不少弯路,有时觉得自己作为API侠,无所不能,有时又觉得自己很多LeetCode题写不出来,无能为力。我有一个博客,但是写满了自己的絮絮叨叨,真正有本领的东西九牛一毛。 我甚至没有自己的“代表作”,因为我是一个急性子,想马上得到结果(事实上计算机真能马上给出结果,但开发过程不行)。我经常在“造自己的轮子”和“用别人的轮子”之间徘徊,“造自己的轮子”比较有成就感,但是难度其实很大,需要踩很多别人踩过的坑;“用别人的轮子”则没有什么成就感,做出来也不像是自己做的。而平时工作中,每天都在用别人的轮子,自己真正从比较底层开始实现的情况是非常少的,导致我在闲暇时间也不想用别人的轮子。 啰嗦一下自己的经历: 2004年,我家买了电脑,我也接触了很多电脑上的游戏。但是也许是我心浮气躁或者没有游戏天赋,我总是在游戏里输,总是追不上邻居小伙伴; 2008年,我萌生了“自己写一个什么东西”的想法。 2009年夏,小学毕业的我开始摆弄魔兽地图编辑器,虽然一点脚本都没写,做出来的游戏也粗制滥造。也开始查找“如何创建一个个人网站”。 2010年,在和初中新同学混熟之后,我们打算做一个班级网站,我找了一圈发现5566和phpwindy有免费的论坛可以注册,我们注册了一个论坛,并且想把每天的作业更新发布上去。但事实上那位同学仅发布过一次作业。 2011年,我利用爸妈给我的打游戏的时间,将网页保存下来,咬着牙研读里面的html标签,然后给我当时加入的一个魔兽争霸群做了一个纯html的“官网”。在某免费空间上注册了一个只支持asp和基础web的免费空间,用8uFTP把网站上传上去。 2014年,在学校的图书室,我昧着良心在寻找Dreamweaver的教程书,还真给我找到了。但是我根本没有自己的电脑,只能对着书发呆脑补。 2015年夏,我高中毕业,填志愿的时候几乎把“软件工程”和“计算机科学与技术”都填的满满的。我查了资料发现“软件工程”比“计算机科学与技术”学费更贵,在询问了父母的意见之后,我把“软件工程”填到了第一位,然后和父母说,一定会考上。最后我考上了一个普通的本科,开始学习软件工程专业。 2015年暑假,还有一件事情,我自己注册了(已经失效了的)域名,购买了阿里云的虚拟主机,配置了WordPress服务器,在上面写博客文章。仅仅是备份就花了一周,然后终于拿到了自己的备案号。我永远不会忘记第一次用自己的域名打开自己的网站那一刻的快乐。 2016年春,我推开软件学院大楼某间实验室的大门,然后就我大学一年级就和学长们一起做项目,当时团队里缺人写html页面,而我正好已经算是html css入门了(完全不会js),开始仿写各大网站。然后想自己写一个象棋游戏,结果找资料就找了一个下午,最后不了了之。 2017年夏,我跟着课程开始研究蚁群算法,最后实现了论文的内容。现在回想起来,对着论文依葫芦画瓢其实没什么技术含量,当打包运行并且在台上汇报之后,我真的觉得很快乐。不过,我并没有学到什么“真才实学”。 2017年秋,在Java课上,我带领团队(其实开发就我一个人)用Bmob作为后端,安卓作为前端,开发了一个“今日特价” app。我对着github上的一个高仿微博的项目,拼命的抄各种代码。而最后我觉得写的太差,而把代码都删除了,真是太可惜了。 2018年,我有了很多很多想法,但是都没有执行下去。 我想自己从零搭建一个博客,用新学的SpringMVC,替换掉WordPress。 我想做一个网站,叫做“预言”,简单来说就是让用户发表一些对未来的猜测,并且定一个时间,然后系统到了那个时间会提醒用户确认是否预言成功 我想做一个安卓app,像三国志11一样,将所有三国的人物,历史事件,城池信息,战役,单挑,舌战都完整地汇总在里面,然后再像游戏一样,将“官渡之战”、“赤壁之战”、“夷陵之战”都像三国志11一样活灵活现地展示在地图上。 当时我觉得做网页做系统已经很没有意思了,所以我决定做机器学习,深度学习。 我想考研,因为不太满意自己的双非学历。 那时候LPL竞猜挺火的,我和朋友商量写一个统计各队伍各选手的评分的系统。当时我先用jQuery写了前端,拼命的append html标签,导致我自己写完的时候都不知道自己在写什么。 2019年春,考研没考上,但是数学二确实也让我复习了高数和线代。借助这点基础,我选了一个“手写汉字识别的研究”的题目,然后开始学习吴恩达的机器学习入门,学习深度学习Tensorflow,学习卷积神经网络等等,然后由于自己的电脑的显卡是1050ti,有点不够用,我就花钱去租专门用于训练的服务器,印象中要6块1小时。那时候为了一个好的结果,,花了不少家里的钱。 2019年春夏之交,我的论文提交给了一个不太懂机器学习的老师,老师一看就觉得我在抄别人的论文。给我的建议是,我要么一意孤行继续这样答辩,但可能延毕;要么就把手写汉字识别改成某个系统,走需求分析,UML设计,数据库设计,开发,测试,结论的框架。当时我感到了深刻的绝望,自信心几乎被击垮,支离破碎。仗着自己之前也曾一个人咬着牙实现过不少系统,我决定把这个算法的研究都丢掉,转用百度提供的手写汉字识别api,包装成一个笔记系统,手写的笔记拍个照就转储成汉字。 2019年秋,我入职某软件公司,我终于会写Vue了。在之前我总是写jQuery。我甚至以为jQuery是最好的解决方案。也许2015年前是,2015年后就不是了。 2020年,我虽然是Java开发工程师,但是做了很多很多前端的内容。我被迫花很多时间去调CSS,去抄别人的js来完成移动端的h5网页的展示效果。我感到非常的厌恶,觉得自己的能力被封锁了。领导想弄区块链,想提供API接口给其他公司使用,但现在看来根本没有任何优势,仅仅是困兽之斗。另外,为了能把智能客服的问答预料快速查找,我学习了ElasticSearch数据库的用法。为了爬取一些信息,我学习了Python开发。 2020年秋,我被“发配”北京,每天都过得很不开心,回家遥遥无期。本来说好的出差一个月,到了地方之后却要求长期驻地开发。而那套系统的代码很乱,找到机会我马上就离职了。 2021年,我来到上海,接触了游戏服务器开发。我第一次发现服务器是如此的庞大。 我学习了新的架构:Actor架构。 我受到网上的信息“蛊惑”,觉得hibernate已经过时,但在游戏这个场景里,hibernate比mybatis更适合。 我以前不理解Zookeeper到底用来做什么,他们总是只教我存和取,现在我知道可以配置系统信息; 我自学过netty,但是不理解为什么要用netty,现在我知道了,封包解包,NIO这些情况用netty确实快人一步。 我以前觉得mysql能力有限,但是在mysql前加一层缓存的话,速度就会成倍提高。还有索引和主键的配置也是有考究的,慢查询也是可以分析的。并不能武断的认为mysql能力不行。 还有一些完全没听过的,比如protobuf,akka,集群,ticker,在我之前的认知里只有json是唯一通信的结构。 2022年,我回过头来发现,我好像是从2021年之后,才真正打破“啥都会,啥都不会”的尴尬局面。在此之前,我好像什么都会: Web前端:html,css,js基础语法,jQuery的用法,简单的WebPack打包,简单的Vue Java后端:SpringMVC过渡到SpringBoot,MyBatis 移动端:基础的Android开发 数据库:使用过关系型的Oracle,mysql,也使用过非关系型的mongodb和ElasticSearch Python:爬虫相关 服务器:只会简单的java -jar部署,netstat -nlp看端口,然后给我所有的电脑都装好双系统。 又啥都不会: Web前端不会最有技术含量的React Java后端不会hibernate,HashMap的底层逻辑,Java虚拟机的垃圾回收机制都是用背的。 移动端:不会用kotlin写安卓,也不知道最新的安卓有什么内容 数据库:从没有仔细学习mysql背后的存储优化原理,也没有上手实操过 服务器:以为服务器只是java -jar,而没有研究过docker,zookeeper,jenkins等更优秀的工具和中间件。装双系统也就装的那一刻用一下,真要做事还是用虚拟机多开…… 没有研究过消息队列。 总的来说就是,都是浅尝辄止。当跑完hello world,把环境搭起来的时候,我就觉得自己行了,牛了,然后关掉编译器去玩了。 不过有意思的是,2021年我在10年工作经验的主程面前点开8uFTP的时候,他惊讶地问:“woc你怎么在用这个东西?太老了这个,可以换一下Filezila”。而我会心一笑。后来团队发生了变动,换了个新主程。在闲暇时间我和他攀谈“网页三剑客”,向他展示我2015年就搭建起来的博客,和他开玩笑说,我和他是同一个软件开发时代的人,我是Young OG! 但也仅此而已了。也许我真的是Young OG,但是我总是缺了点什么很关键的东西。以前我觉得自己不懂坚持,总是半途而废,而现在,在上海工作了一年多之后,我发现我的能力并没有任何问题,我的问题在于不知道怎么将工作切分,不知道怎么保存自己的体力,不知道自己的目标是什么。 不管是写LeetCode,写项目,还是研究某个新框架,都需要安排时间,都需要统筹自己拥有的资源。特别是写项目,写项目有一点像写小说。只有将小说里每个章节都完成并且有所关联(长篇小说),才能是一部优秀的小说。长篇小说家也不是一朝一夕能写完一部大作,我们软件开发人员自然也不能一朝一夕写好一个系统,更何况我们还需要测试自己的代码。 所以我们需要对任务进行切分。 任务切分的方法和意义 最近两三个月,在工作中,我开始使用画图工具来画一些流程图或者架构图。这些图不是标准的UML图,但是是我自己能看懂的图。...

April 5, 2022 · 1 min · JohnathanLin

使用Python实现简单UDP Ping

套接字编程作业2:UDP ping 程序 在本实验中,您将学习使用Python进行UDP套接字编程的基础知识。您将学习如何使用UDP套接字发送和接收数据报,以及如何设置适当的套接字超时。在实验中,您将熟悉Ping应用程序及其在计算统计信息(如丢包率)中的作用。 您首先需要研究一个用Python编写的简单的ping服务器程序,并实现对应的客户端程序。这些程序提供的功能类似于现代操作系统中可用的标准ping程序功能。然而,我们的程序使用更简单的UDP协议,而不是标准互联网控制消息协议(ICMP)来进行通信。 ping协议允许客户端机器发送一个数据包到远程机器,并使远程机器将数据包返回到客户(称为回显)的操作。另外,ping协议允许主机计算它到其他机器的往返时间。 以下是Ping服务器程序的完整代码。你的任务是写出Ping客户端程序。 服务器代码 以下代码完整实现了一个ping服务器。您需要在运行客户端程序之前编译并运行此代码。而且您不需要修改此代码。 在这个服务器代码中,30%的客户端的数据包会被模拟丢失。你应该仔细研究这个代码,它将帮助你编写ping客户端。 # UDPPingerServer.py # We will need the following module to generate randomized lost packets import random from socket import * import random # Create a UDP socket # Notice the use of SOCK_DGRAM for UDP packets serverSocket = socket(AF_INET, SOCK_DGRAM) # Assign IP address and port number to socket serverSocket.bind(('', 12000)) while True: # Generate random number in the range of 0 to 10 rand = random....

November 13, 2021 · 2 min · JohnathanLin