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

23年3月23日,我在公司进行了一次分享会,内容是本文的内容。在分享前,我重新对文章知识点进行了梳理,补充了很多细节。现将补充的细节重新编写到本文中。 什么是二进制数? 我们日常使用的是十进制,数字包括0,1,2,3,4,5,6,7,8,9 再往下数,就得向前进一位,变成10,然后从个位数开始继续增加11,12,13…19 计算机最底层使用的是二进制,数字包括0和1,再往下数,也是前进一位,变成10。注意,这个10并不是十进制的十,而是十进制的二。 如何用二进制来表示一个整数? 二进制 十进制(无符号) 0000 0 0001 1 0010 2 0011 3 0100 4 0101 5 0110 6 0111 7 1000 8 1001 9 1010 10 1011 11 1100 12 1101 13 1110 14 1111 15 二进制如何表示负数? 原码 我们把最高位(最左边的位)作为符号位,后面剩余的位代表的数作为数值具体的大小。 比如:四位原码二进制表示数字 — 3 1 011 开头的1代表负号,后面的011表示3。这样拼起来就是负3了 但是这么表示可能会有什么问题? 原码表示负数存在的问题 0000和1000,都是表示数字0,但是一个是正0,一个是负0。这显然不符合我们对零的理解。 无法进行加减运算:观察以下式子1(0001) + (-3(1011)) = -4(1100) 0001 +1011 -——- 1100 那么如何用二进制表示一个数字,才能处理加减操作呢? 补码 以时钟为例,拨动时钟理解补码 把红色指针从指向“8”拨动到“6”, 有几种方式? 有两种方式,如图所示: 以此图为例,如果指针目前指向8(红色指针),要把它拨到6(绿色指针),有两种方式: 把8往逆时针方向旋转到6(蓝色)这种方式就是进行8-2=6 把8往顺时针方向旋转到6(黄色)这种方式是进行8+10=18,但是时钟只能显示12个数字,所以18-12=6 补码减法的逻辑是:通过加法,给数字加上一个超过表示上限的数,使其最高位“丢失”的方式来实现减法。...

四月 30, 2023 · JohnathanLin

Windows XP虚拟机中文版无需激活下载

在这里直接下载我最后完成的虚拟机镜像 虚拟机镜像下载: 链接:https://pan.baidu.com/s/1yfY0SjDrtOeuTiEWf7YizA?pwd=374l 提取码:374l 我本地的VirtualBox 版本:6.1 我可以先聊聊怀旧吗 也许对于老外来说,Win95是他们的青春,所以他们做了React95这样的UI库,或者大家一起努力写了个操作系统serenity。但是对于咱们国内的用户而言,当家用PC走进千家万户时,映入眼帘的是——Windows XP。 一位中国台湾同胞sh1zuku编写开发了一个网页版的Windows XP模拟器:项目链接,在线演示,还有另一位来自越南的老哥khang-nd写了Windows 7的网页模拟器在线演示。 我自然没有能力和时间去编写类似系统的开发,但是有一个想法从我的脑中浮现:那么我就装一个Windows XP虚拟机到电脑上就好了。 你可能会选择的做法 安装VirtualBox; 下载镜像:从MSDN Itellyou中找到Windows XP的镜像,下载; 在VirtualBox中安装镜像; 启动镜像,安装系统 那么你会发现,安装的Windows XP只有30天试用。在二十一世纪初期,盗版泛滥,微软采取了非常强硬的措施限制盗版。即使你安装时输入了正确的序列号,微软也会要求你使用电话等方式进行激活。 但是我们是来怀旧的啊! 正确的做法 不能再使用这种正版的镜像了,需要使用别人处理好的,不需要激活的镜像。 这里我找到了github上的一位老哥提供的链接github WinXPImage,但是他的镜像是位于谷歌云盘上的。我把它下载之后放进百度网盘里了: 链接:https://pan.baidu.com/s/1ypKeaZixJXnbqAo4ZT0YLQ?pwd=30dd 提取码:30dd 在VirtualBox安装此镜像后,你将获得一个无限期使用的,英文版的Windows XP。 但你不一定能启动起来,你需要在导入OVA文件后,在OVA文件的目录下,执行以下命令: vbox-img geometry --filename Windows_XP_Professional-disk1.vdi --format VDI --cylinders 5874 --heads 255 --sectors 56 来自于github issue streeg 老哥给出的解决方案。 如何汉化Windows XP? 如果只是用英文版Windows XP,那么就达不到我们“怀旧”的目的了。 Windows XP英文版默认没有中文语言包。 我翻遍互联网,终于在一个犄角旮旯里找到了语言包mui_win_xp_pro_n_cd1.iso。 我把它下载之后放进百度网盘里了: 链接:https://pan.baidu.com/s/18mW9OCRejMDoEpUcih-zlA?pwd=peu4 提取码:peu4 然后, 设置VirtualBox里Windows XP虚拟机和物理机共享文件夹,具体方法 将mui_win_xp_pro_n_cd1.iso通过共享文件夹从物理机传进虚拟机中 安装,具体方法 最后重启虚拟机即可。 上图!

十月 2, 2022 · JohnathanLin

Java TreeSet的一些用法和特性

先看一个例子(kotlin实现) import java.util.TreeSet /** * 定义一个用于测试TreeSet集合的结构 * 用TreeSet进行排名 * id: 玩家id * score: 玩家得分 */ data class PlayerScore(var id: Int, var score: Int): Comparable<PlayerScore> { override fun compareTo(other: PlayerScore): Int { return if (score > other.score) { 1 } else if (score < other.score) { -1 } else { 0 } } } fun main() { //创建一个TreeSet val treeSet: TreeSet<PlayerScore> = TreeSet() //创建3个PlayerScore,其中对id为101的对象存一个引用 //将3个PlayerScore装入set中 val id101Obj = PlayerScore(101,100) //按不同的顺序加入TreeSet treeSet.add(PlayerScore(102,200)) treeSet....

六月 18, 2022 · 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设置属性,作为服务端,为了方便? 可以设置重用地址和端口号。 int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); 为了重用地址和端口号,需要这么做: level传SOL_SOCKET,代表你这次设置的属性值是给哪个模块用的 optname传SO_REUSEADDR|SO_REUSEPORT,代表你打算同时设置这两个属性 optval传一个int*指针,指向某一个数字 optlen传sizeof()上面的optval C++ socket很多函数都需要你再传一个length长度,以确定你真正想传给这个函数的数据是多长。...

四月 30, 2022 · 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中。 配置信息读取 对于智能客服来说,由于并发量业务量很少(因为投放的平台比较少,且晚上凌晨基本没什么人使用,且重启速度很快),有一些需求上的配置数值(比如发送几次“转人工”才进入转人工通道)是直接硬写在业务里的;也有一些配置信息是其他系统的请求地址url,会配在application.properties里。没有使用excel统一存储各个功能模块的配置信息,也确实不需要。 但对于游戏来说,数值这块的配置至关重要,与玩法,奖励,游戏内生态息息相关。因此在游戏服务器里,所有的数值几乎都要从配置表中读取。目前Excel应该是处理数据能力最强的软件了,策划可以通过Excel非常快速的把数值配好。 启动服务器的时候要读取配置表到内存(广义上的)里。但在有了zookeeper这样的工具出现之后,配置表数据可以放在zk中,需要的时候再取出来。 游戏服务器优势 传输结构为protobuf 服务器接收和发送的数据都是ProtoBuf转成的二进制,从而实现客户端服务器端统一的传输结构。protobuf自己有编码解码二进制的功能,从而实现消息数据的大小达到最小,编码解码是由netty执行的,使用上只需要将protobuf生成的对象传给netty即可。这边用的protobuf是v2版本的,有required,optional和repeated三种关键字,分别对传输message里的属性作出了约束。 Akka Actor架构 Actor架构实现单线程的业务逻辑,开发过程中不需要对一些公用的属性上锁;通过内部消息的通讯,让数据处理有序进行。Akka cluster集群有动态负载均衡的功能,可以进行平行扩展,也就是说,如果一台服务器扛不住并发,只要再配置一台或几台新服务器,加入集群就可以完成负载均衡。...

四月 16, 2022 · JohnathanLin