目录
- ASCII码表
- ASCII打印字符
- ASCII非打印控制字符
- ASCII扩展打印字符
- C语言基本数据类型
- 整型变量
- 整型常量
- 实数(浮点)类型
- 实型(浮点)常量
- 字符变量
- 字符常量
- C语言中printf打印形式
- %2d,%-2d,%.2d,%02d,%ld,%lld
- %f, %.nf, %m.nf
- %2x, %02x, %-2x, %.2x
- %e, %.2e,%3.2e
- Docker
- 鉴权(鉴定是否有权访问)
- 数字签名
- Cookie、Session、Token之间的区别
- POSIX
- 为什么IP数据报使用分片偏移来标识分段,而不直接采用序号
ASCII码表
参考地址:https://blog.csdn.net/sinat_28631741/article/details/80961033
ASCII码大致由三部分组成:
ASCII打印字符
数字 32–126 分配给了能在键盘上找到的字符,当您查看或打印文档时就会出现。注:十进制32代表空格 ,十进制数字 127 代表 DELETE 命令。下面是ASCII码和相应数字的对照表:
ASCII非打印控制字符
ASCII 表上的数字 0–31 分配给了控制字符,用于控制像打印机等一些外围设备。例如,12 代表换页/新页功能。此命令指示打印机跳到下一页的开头。
ASCII扩展打印字符
扩展的 ASCII 字符满足了对更多字符的需求。扩展的 ASCII 包含 ASCII 中已有的 128 个字符(数字 0–32 显示在下图中),又增加了 128 个字符,总共是 256 个。即使有了这些更多的字符,许多语言还是包含无法压缩到 256 个字符中的符号。因此,出现了一些 ASCII 的变体来囊括地区性字符和符号。
C语言基本数据类型
参考:语言基本数据类型
针对不同的数据,采取不同的存储方式和进行不同的处理。随着处理对象的复杂化,数据类型也要变得更丰富。数据类型的丰富程度直接反映了程序设计语言处理数据的能力。
C语言很重要的一个特点是它的数据类型十分丰富。因此,C语言程序数据处理功能很强。C语言丰富的数据类型可归纳如下:
整型变量
整数类型数据即整型数据,整型数据没有小数部分的数值。整型数据可分为:基本型、短整型、长整型和无符号型四种。
基本型:以int表示。
短整型:以short int表示。
长整型:以long int表示。
无符号型:存储单元中全部二进位用来存放数据本身,不包括符号。无符号型中又分为无符号整型、无符号短整型和无符号长整型,分别以unsigned int,unsigned short和unsigned long表示。
要注意的是,不同的计算机体系结构中这些类型所占比特数有可能是不同的,下面列出的是32位机中整型家族各数据类型所占的比特数。
虽然int与unsigned int所占的位数一样,但int的最高位用作了符号位,而unsigned int的最高位仍为数据位,所以它们的取值范围不同。
若要查看适合当前计算机的各数据类型的取值范围,可查看文件“limits.h”(通常在编译器相关的目录下),如下是“limits.h”的部分示例。
#define CHAR_BIT 8 /* number of bits in a char */
#define SCHAR_MIN (-128) /* minimum signed char value */
#define SCHAR_MAX 127 /* maximum signed char value */
#define UCHAR_MAX 0xff /* maximum unsigned char value */#ifndef _CHAR_UNSIGNED
#define CHAR_MIN SCHAR_MIN /* mimimum char value */
#define CHAR_MAX SCHAR_MAX /* maximum char value */
#else
#define CHAR_MIN 0
#define CHAR_MAX UCHAR_MAX
#endif /* _CHAR_UNSIGNED */#define MB_LEN_MAX 2 /* max. # bytes in multibyte char */
#define SHRT_MIN (-32768) /* minimum (signed) short value */
#define SHRT_MAX 32767 /* maximum (signed) short value */
#define USHRT_MAX 0xffff /* maximum unsigned short value */
#define INT_MIN (-2147483647 - 1) /* minimum (signed) int value */
#define INT_MAX 2147483647 /* maximum (signed) int value */
#define UINT_MAX 0xffffffff /* maximum unsigned int value */
#define LONG_MIN (-2147483647L - 1) /* minimum (signed) long value */
#define LONG_MAX 2147483647L /* maximum (signed) long value */
#define ULONG_MAX 0xffffffffUL /* maximum unsigned long value */
在嵌入式开发中,经常需要考虑的一点就是可移植性的问题。通常,字符是否为有符号数会带来两难的境地,因此,最佳妥协方案就是把存储于int型变量的值限制在signed int和unsigned int的交集中,这可以获得最大程度上的可移植性,同时又不牺牲效率。
整型常量
C语言整型数据一般有十进制整数、八进制整数和十六进制整数三种表达形式。说明如下。
- 十进制整数的表示与数学上的表示相同,例如:256,-321,0
- 八进制整数的表示以数字0开头,例如:0234表示八进制整数(234)8,所对应的十进制数为 。2×82+3×81+4×80=156。
- 十六进制整数的表示以0x开头,例如:0×234表示十六进制整数(234)16。(应当注意的是十六进制数前导字符0x,x前面是数字(0)。
在一个整型数据后面加一个字母L或l(小写),则认为是long int型量。如342L、0L、78L等,这往往用于函数调用中。如果函数的形参为long int型,则要求实参也为long int型,此时需要用342L作实参。
实数(浮点)类型
1.实数(浮点)变量
实型变量又可分为单精度(float)、双精度(double)和长双精度(long double)3种。列出的是常见的32位机中实型家族各数据类型所占的比特数。
要注意的是,这里的有效数字是指包括整数部分+小数部分的全部数字总数。
小数部分所占的位(bit)越多,数的精度就越高;指数部分所占的位数越多,则能表示的数值范围就越大。下面程序就显示了实型变量的有效数字位数。
#include<stdio.h>
int main()
{float a;double b;a = 33333.33333;b = 33333.333333;printf(" a = %f , b = %lf \n" , a , b );return 0;
程序执行结果如下:
a=33333.332031 , b=33333.333333
可以看出,由于a为单精度类型,有效数字长度为7位,因此a的小数点后4位并不是原先的数据。而由于b为双精度类型,有效数字为16位,因此b的显示结果就是实际b的数值。
实型(浮点)常量
在C语言程序设计中,实型数据有以下两种表达形式。
- 十进制数形式。由正负号、数字和小数点组成。如5.734、一0.273、0.8、一224等都是十进制数形式。
- 指数形式。如546E+3或546E3都代表546×10 3。字母E(或e)之前必须有数字,E(或e)后面的指数必须为整数。
E8、4.6E+2.7、6e、e、9E7.5都是不合法的指数形式;
5.74E-7、-3E+6是合法的指数形式实型常量。
字符变量
字符变量可以看作是整型变量的一种,它的标识符为“char”,一般占用一个名节(8bit),它也分为有符号和无符号两种,读者完全可以把它当成一个整型变量。当它用于存储字符常量时,实际上是将该字符的ASCⅡ码值(无符号整数)存储到内存单元中。
实际上,一个整型变量也可以存储一个字符常量,而且也是将该字符的ASCH码值(无符号整数)存储到内存单元中。但由于取名上的不同,字符变量则更多地用于存储字符常量。以下一段小程序显示了字符变量与整型变量实质上是相同的。
#include<stdio.h>
int main()
{char a,b;int c,d;
/*赋给字符变量和整型变量相同的整数常量*/a=c=65;
/*赋给字符变量和整型变量相同的字符常量*/b=d='a';
/*以字符的形式打印字符变量和整型变量*/printf("char a=%c,int c = %c", a,c);
/*以整数的形式打印字符变量和整型变量*/printf("char b=%d,int d=%d\n",b,d);
return 0;
程序执行结果如下:
char a=A,int c=A;
char b=97,int d=97;
由此可见,字符变量和整型变量在内存中存储的内容实质是一样的。
字符常量
字符常量是指用单引号括起来的一个字符,如:‘a’,‘5’,‘?’ 等都是字符常量。以下是使用字符常量时容易出错的地方,请读者仔细阅读。
- 字符常量只能用单引号括起来,不能用双引号或其他括号。
- 字符常量只能是单个字符,不能是字符串。
- 字符可以是字符集中任意字符。但数字被定义为字符型之后就不能参与数值运算。如’5’和5是不同的。‘5’是字符常量,不能直接参与运算,而只能以其ASCⅡ码值(053)来参与运算。
除此之外,C语言中还存在一种特殊的字符常量——转义字符。转义字符以反斜线“\”开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。
例如,在前面各例题printí函数的格式串中用到的“\n”就是一个转义字符,其意义是“回车换行”。转义字符主要用来表示那些用一般字符不便于表示的控制代码。
常见的转义字符以及它们的含义。
‘0’ 的ASCII码 48,‘A’ 的ASCII码 65,‘a’ 的ASCCII码 97
C语言中printf打印形式
%2d,%-2d,%.2d,%02d,%ld,%lld
%d:普通的输出,是几位数就输出几位数。
%2d:按宽度为2输出,右对齐方式输出。若不够两位,左边补空格。
%02d:同样宽度为2,右对齐方式。位数不够,左边补0。
%.2d:从执行效果来看,与%02d一样。
%-2d:-号表示右边补空格
%ld:输出long
%lld:输出long long (在32位编译器上,int=long=32bit;long long=64bit)
#include<stdio.h>
int main()
{int a = 1;printf("%d\n",a);printf("%2d\n",a);printf("%02d\n",a);printf("%.2d\n",a);printf("%-2d\n",a);return 0;
}
%f, %.nf, %m.nf
%f:不限制宽度和小数点后面的位数
%5.2lf:表示限制数据输出宽度为5,小数点后保留2位。不足宽度的前面补空格。超过宽度的数据正常输出。
%.2f:表示小数点后面保留两位小数。
%.6f:表示小数点后面保留六位小数。
#include<stdio.h>
int main()
{double num;num = 3.1415;printf("%f\n",num);printf("%5.2lf\n", num);printf("%.2lf\n", num);printf("%.6lf\n", num);return 0;
}
%2x, %02x, %-2x, %.2x
x:表示以十六进制形式输出,
%02x: 表示不足两位,前面补0输出;如果超过两位,则实际输出
%.2x:效果和%02x相同 (%02x=%.2x)
%2x:表示数据不足两位时,前面补空格; 如果超过两位,则实际输出
%-2x:表示数据不足两位时,后面补空格; 如果超过两位,则实际输出
#include<stdio.h>
int main()
{printf("%02X\n", 0x255);printf("%02X\n", 0x5);printf("%2X\n", 0x255);printf("%2X\n", 0x5);printf("%-2X\n", 0x5);return 0;
}
%e, %.2e,%3.2e
%e : 以指数形式打印数字 在不指定输出宽度的情况下默认数字部分小数点6位,指数占4位。 注意:小数点不算小数部分,指数e与 + / -都算指数位数。
% m.ne : m表示输出列数,n表示有几位小数 当输入列数 > m时按原数据输出 当 < m时前补空格输出
% -m.ne:表示后面补空格。
% .2e:表示不限制输出列数,小数部分保留2位。
#include<stdio.h>
int main()
{printf("%e\n", 123.456);printf("%.2e\n", 123.456);printf("%13e\n", 123.456);printf("%-13e#\n", 123.456);printf("%13.2e\n", 123.456);printf("%-13.2e\n", 123.456);return 0;
}
Docker
Docker:https://zhuanlan.zhihu.com/p/510757832
鉴权(鉴定是否有权访问)
百度百科:https://baike.baidu.com/item/%E9%89%B4%E6%9D%83/10857773?fr=aladdin
鉴权(authentication)是指验证用户是否拥有访问系统的权利。传统的鉴权是通过密码来验证的。这种方式的前提是,每个获得密码的用户都已经被授权。在建立用户时,就为此用户分配一个密码,用户的密码可以由管理员指定,也可以由用户自行申请。这种方式的弱点十分明显:一旦密码被偷或用户遗失密码,情况就会十分麻烦,需要管理员对用户密码进行重新修改,而修改密码之前还要人工验证用户的合法身份。
为了克服这种鉴权方式的缺点,需要一个更加可靠的鉴权方式。主流鉴权方式是利用认证授权来验证数字签名的正确与否。
逻辑上,授权发生在鉴权之后,而实际上,这两者常常是一个过程。
我们常用的鉴权有四种:
- 1、HTTP Basic Authentication
- 2、session-cookie
- 3、Token 验证
- 4、OAuth(开放授权)
数字签名
AWS IOT Device C SDK 使用(阿里云一机一密、一型一密、公钥、私钥、CA、根证书、签名、验签、哈希、X.509)
Cookie、Session、Token之间的区别
Cookie、Session、Token之间的区别:https://v.douyin.com/MpqohSr/
- 1、存储的位置不同,cookie数据它是保存在客户端里面的,Session数据它是存储在服务器中,服务器存储相对于客户端来说是更为安全的;
- 2、存储的数据类型不同,两者虽然都是key value的数据结构,Cookie的value它只能是字符串的类型,session的value它可以是object类型,就是所有的数据类型它都能支持;
- 3、存储的数据大小不同,cookie的大小会受到浏览器的限制,一般限制在4k的大小,而Session理论上来说他只受内存的限制;
- 4、生命周期的区别,cookie的生命周期就是浏览器如果关闭的话他就会消亡,而且他还有对应的超时限制,就是你无论有没有访问,只要超时时间一到,它就一定会过期。Session是取决于服务端的一个设定,它可以设置成用户持续访问,他就不永远不会失效,和浏览器的开关是没有关系的。
- 5、有的面试官他可能关注这个点,Cookie、Session之间它是有什么样的联系?首先你们要知道Cookie它是Session的一种应用,FTP、HTTP是无状态的,服务器他只能获取到请求来源的IP,它是获取不到用户身份信息的,服务器它可以用Session存储用户的数据,一般客户都会写一个Session_ID存放在那个cookie里面,比方说这样的数据:set-cookie:session_id=123456;expires=12351233。
- 6、token也是写在cookie上的,存储在客户端,服务端会校验token的正确性。
Cookie、Session、Token之间的区别: https://v.douyin.com/MpXrCFu/
首先来讲,为什么会有cookie、session、token这样的东西,我们先来讲这个HTTP的无状态连接的概念,HTTP网络协议下所有的请求,他都是无状态连接的。所谓的无状态连接就是我A接口的请求跟B接口的请求,他们彼此之间是没有任何的关系。我每一个接口的请求业务,他都是独立化存在的,比如说我们访问了一个登录接口,在我提示到登录成功的这个信息获取成功以后,当我系统反馈到一个你已经登陆成功了,这个时候我们再来去操作其他内容的时候呢,系统会返回一个新的返回结果,告诉我们说请登录,比如我们先登录,登录完了之后我们去查询我们的用户信息,这个时候你会遇到一个问题,就是你登录它提示你登录成功,但是你在查询信息的时候,他会告诉你请登录之后再来尝试,或者说诸如此类的这种提示。这是为什么呢?就是因为HTTP是无状态连接的特性。这个特性意味着我们的登录接口跟获取用户信息的接口,两者没有任何的关系,对于系统而言,它是两个完全独立,没有关联的两次不同的请求,我分别对他们来进行处理。这个处理过程中,我不会因为他们两个接口本身业务有关联,我就把它关联起来,因为对于系统来讲,它就是两个单独独立存在化的个体。
但是有同学可能就会说,我自己在做这个系统的测试的时候,我在用户登录之后,系统是保存了我的登录信息的。系统它显示我一直处于登录状态,而且我在操作过程中,我也并没有出现到你所讲到的这种无状态的情况,我只执行了一次登录,我能够通过这次登陆之后,我能够去获取用户信息,我能调用用户数据,我能基于这个用户去干很多很多的业务场景。这个是为什么呢?这个就必须讲到的第二点,就是我们接口的鉴权机制(参考上面词条解释)。为了满足整个系统中数据交互的一个合理化,我们需要考虑用一些特定的手段去解决掉HTTP网络协议的无状态属性。为什么说HTTP它本身不会自己解决这个问题,很简单,因为HTTP目前被认定为是人机交互下效率最高的一种传输协议,他是人机交互之间传输速率最高的一种传输协议。这个协议之所以效率最高,就是因为它的无状态连接。所以说这个东西是没有办法去取消的,而我们在业务的实现过程中,我们想要去一次登录,让用户这个能够成功的登陆,并且能够持续的访问我们的系统的话,我们就要考虑在接口的业务处理上面增加一个鉴权机制,健全机制就是说当我用户登录成功以后,我去做其他的操作的时候,我的系统就会通过这个健全机制来鉴定该用户,或者说当前的这个产生提交数据的这个行为的用户,他是否具备有这样的一个权限来做接下来你想要的操作。比如我们的这些视频平台的VIP,你如果没有开通VIP的话,有些视频是看不了的,或者说你需要额外付费才能看到,当你是VIP之后,你才可以去看,这个就是一个典型的鉴权机制。那这个接口下的这个健全,就是上面讲到的cookie session 和 token。
Cookie的这种模式,就是我们服务器在处理运算数据之后,它会生成一批的响应结果,这个响应结果同时呢,它会包括包括一个叫做响应头的,在响应头中会定义一个叫set cookie的字段,服务器返回来的所有的数据包当中。set cookie当中所明确标志的内容就是你需要存入到cookie当中的东西,你必须要存储到用户端的本地,这个存放是以键值对,也就是key value的这种格式进行保存的一种文本信息,就是cookie。那么这个cookie有什么用呢?在我们第一次访问完了系统中生成了一批量的cookie数据,保存到我的用户端的本地之后,当我下次再在我的这个本地的用户去访问这个系统的时候,就可以把这些cookie所带有的这些文本信息直接带上一并传递过去。然后系统通过你的cookie传递过来的这些数值,来判定你这个用户之前是否有访问过我的系统,你这个用户访问系统的时候,你具备一些什么样的权限,就可以在cookie当中去添加这样的一些权限码。这个权限码就包括我们接下来讲的session和token,我们都可以通过cookie来进行保存,这个东西是在用户本地的。
session,中文名字叫做临时会话。本身是一个临时会话的机制,你的HTTP是无状态的连接,我在用户端访问到服务端的时候,我就建立一个类似于会话窗的这样一个窗体,类似于一个一对一的聊天框,当我们建立了这个聊天框之后,我与服务器之间的沟通和数据的交互都通过这个聊天框来进行。我有这个聊天框存在,我就可以不停的给服务端发送数据,服务端也可以不停的给我发送数据,这个就是聊天框在中间的作用。session就是这个聊天框,它有这样的一个空间啊,开辟出了一个临时会话的空间,在这个空间当中相当于建立了用户与服务端之间的这个联系。所有的数据交互都通过这个空间来进行处理。服务器这边大家可以想啊,我有1万个用户来访问的服务端,服务端就有1万个session的这个空间,那么这么多的空间我该怎么去管理,我怎么能够对应到哪个用户是使用的哪一个session的会话框呢?很简单,我们在session的这个机制当中,我们给每一个会话框,我们标了一个类似于ID这样的一个数值,叫做session ID,我们就通过用session ID去标记每一个不同的会话框,这样子就可以清楚地去区分到1万个用户。
token,其实就是一个身份牌,是由服务端在进行用户的数据提交的时候,比如说我向服务端请求一些数据,我们去登录,服务端这边,他就基于我提交的信息去做他的业务逻辑的查询啊,去做业务逻辑的这些处理和运算,然后返回一个成功的结果,与此同时会生成一个叫做token的身份牌,这个身份牌就类似于说我的个人认证啊,我在这个系统当中所谓的一个用户具备有权限的,这个被系统认可的权限的。我只要拿着这个token的身份牌,就可以一直在这个系统里面访问。像是这些视频网站,百度搜索这样的一些网站,我们搜索完了之后进入到这个系统进行登录,登录完成之后,我们做一系列所有操作,等到我们把浏览器关掉,再重新开启浏览器的时候,浏览器一直显示的依旧是我们的一个已登录的状态。这个登录状态是凭什么来的呢?就凭我的这个token,而前面我们所讲到的cookie,这个通用服务端返回cookie,然后这个token保存在了cookie当中,把这个token的值保存进来,当启动浏览器访问我系统的时候,我的本地cookie,我就把这个token就带着一起来访问到我的服务端,服务端接收到这个存在,就默认他为存在的用户,然后它的用户的对应的信息内容是什么,我就把它显示出来,所以我们可以每次打开浏览器都可以有一个默认已登陆的状态,这个就是因为cookie加token在中间起到的作用,这个就是三者的一个基本的作用。
Cookie这个东西它好在什么地方呢?它是以纯文本的形态去保存,保存在用户本地,以键值对的形态去管理它,那我们不同的域啊,就是不同的这个系统在访问的时候,不同的URL去访问的时候。我们的这个不同的URL下面有不同的cookie文件,这些文件呢它就可以很好的去保存每一个域下面的所有的资料啊这些需要被加载的这些cookie的资料他都可以去保存,服务端就不用去管理了,所有东西都在用户端去管理,服务端的压力会很轻松。
但是他有个很大的问题就是因为它是在用户本地以文本的形式保存的这种cookie文件,所以它很容易遭到窃取和手动的修改,那么出现这种情况提交到服务端之后你的账户相关的一些cookie信息,比如说我现在访问了服务端我生成了一个cookie文件,这个cookie文件被人盗用了然后放到他那边的电脑上面,然后他通过这个cookie文件去访问到这个系统就可以获取到我的数据。Session的优劣是什么呢?我们通过一个ID的形式去有序地管理所有的session会话,这样用户可以保持长时间的跟系统之间的数据交互,是非常方便的一个操作。
但同样的这个东西会有一些不太好的问题啊。比如说第一个这个画框如果他长时间的去保存,但是用户与服务端之间又不进行通信的话,那么这个资源就浪费在这里了,我们需要专门开辟一个空间来做服务端与用户端的一个交互。慢慢你服务端的资源他就不够用了啊,它会占据你很多服务端的资源。另外随着用户的使用数量越来越多,我们需要同时去为一些非常非常多的session,这个时候对于服务端来讲,他是要分出很大一部分的资源来管理所有的session,就是我们服务端的资源也无形中就被压榨了很多啊,这就会极大地影响到我们服务端的这个资源啊。为什么会这么讲呢?因为我要开辟出来这个空间,放到这里去交互,那所有的内容都是由我服务端去管理的,而对于你用户端而言,你用户端只需要带着一个session ID来请求我,我就根据你请求过来session ID,我就在这个session的会话框的这个集群里面,我就开始找这个ID匹配的是哪一个啊,匹配到了,我们就继续。那所有的资源都是在服务端管理的,所以他对于服务端的花费是非常非常大的。Token的好处就在于我们服务端生成一个token字段,我不需要通过session的会话了,我就只需要生成一个token字段,这个token字段生成之后,传递给到了用户端,用户端在他本地以K V的这种键值对的形态保存在cookie当中,那么用户拿着这个tooken来访我的系统,系统通过一个算法的解析,把这个token的这个值解析完之后,确保你这个用户是存在的,是正确的,我就给到你一个对应的数据的交互,那么这个时候我就不需要有session,我也不需要去管理这个session的空间,那由此我服务端就把所有的压力给到了用户端,用户端其实也没有什么压力啊,就是保持一个token字段而已,但对于服务端来讲呢,它就不需要再去额外开辟空间去管理所有的session,他只需要提供一个tooken进来的这个解析和识别和校验的这种处理手段就可以。
还有另外一个比较优秀的事情是什么呢,就是我们通过session呢他从服务层的啊,服务器的架构层级上面啊,就是在传统的cookie session token的这个基础上面啊,咱们做一个稍微的升级,我们的session这套机制在管理用户信息的时候呢,它会有一个非常大的弊端,是在架构层级的弊端,就是当你采用集群分布式或者说微服务架构的这种形态来做这个用户的session管理的时候。他往往会出现一个问题,什么问题?如果说我有三个登录服务器,我用户是跟A登录服务器来进行交互生成的这个session呢,那么这个session的管理呢,就会在A服务器上,对于B和C呢,它是没有管理的,那可能有些人会说,那我们给B、C做个同步不就好了吗?那你们想啊,我1万个用户,我之所以做成这种集群的形态,就是为了去减轻服务器的压力,对吧?我1万个用户,3万在这里,3万在这里,3万在这里,OK,我的用户就均摊了。那如果说我要把session做同步的话,那相当于说我每台服务器只有3万个用户在访问,但实际上我三台服务器开辟了9万个session的管理空间。因为你要同步嘛,那么二。这个模块下面就要把一和三的这些session的空间全部都要同步到二里面,那这时候其实二它本身只有3万个用户在使用,但是我要开辟9万个session的空间去管理。是不是无形中资源又有了一个大的耗费,当然这个行不行呢,这个也行啊,但这样子的话,对于资源的浪费比较大。所以说这个是session当中存在有一个非常非常大的问题。我们换另外一种处理模式,我们返回一个token,我这个a服务器他挂掉了啊,我还有B和C服务器,但是我带有这个token,我进到这个服务器里面,我们的算法校验token的机制都是一样的,我这个二服务器也好,三号服务器也好,我用户带着这个token访问进来之后,我只需要去解析你的token就能够无缝对接。因为他们这边提供的就只是一个算法来解析你的token字段,所有的数据都不是保存在某一台服务器上。对吧,那这个时候我们的token,他的一个优势就非常非常明显了。然后同样的token的这种形态,它可以很好的很轻易的就把用户的所有信息在整个服务器集群里给关联起来,这时候它能够带来一个非常非常好的优势。那你说那是不是所有都token可能也不一定。这个还是结合到业务来走,有些东西可能还是用session,有些东西呢,我们会用到token。token这个东西,它随着现在的发展,早期我们的token管理它是这样子的,早期我们是直接把这个数据存放到一个数据库里面,就是DB,在数据库里面生成一个临时表,叫做token的表,因为他们是有时效性的,我们生成token之后,就临时存在这个数据库的这个临时表当中。当我的token进来之后,我就到这个数据库当中获取我本来保存的token,然后跟他去对比,看是否有匹配的,有匹配就通过没匹配,就就提示你重新登陆。但是我们每一次的请求,因为是无状态嘛,每一次请求我们都要把这个内容给传进来,然后在物理数据库当中去寻找,这个速度就会非常慢,所以由此我们就进阶到了基于redis啊走缓存数据库这种形式来做,他就不再需要调动到我的物理数据库,我把这个token的字段全部存放到redis当中去啊,专门开放一个空间去管理他,这个阶段呢,它相较于DB这种数据库的形态更好一些,但是还是会有问题啊,因为你token越来越多,我这个空间占用就会越来越大,我这个总要开辟空间去管理所有的,有100万个用户来访问,那我就升成100万个token,而且这个我还不能随便删,token还有个时效性,可能是一个星期,可能是30天,可能是一年,这个时效性存在的时间内,我都不敢删掉他。那么到了这里怎么办呢?他又会占有很多空间,由此我们就做了一个算法啊。一个math数学的算法,这个算法就是当我的token传进来之后,我不再通过缓存数据库,我也不再通过我的数据库,我通过一个算法接收到这个token,我去做一个正向的加密计算,我基于本地,你token这边带过来的其他的这些数据,我生成对应的一个token,我来比对你传过来的token跟我生成的这个token是否一致,如果是一致的,咱们就认为你是成功的,如果不一致,咱们就认为你的token有问题,那就提示你重新登陆。
cookie只是作为一个本地的键值对的文本信息的保存和管理的,用于将服务端这边指定要保存的这些文本信息保存在客户本地的一个机制而已,session就是临时会话,token就是临时身份令牌啊,三者的区别就非常明显了。
Token:https://www.cnblogs.com/xiaozhijia/p/16216845.html
token有多种意思:1、作为计算机术语时,是指令牌,是一种能够控制站点占有媒体的特殊帧,以区别数据帧及其他控制帧;
1、作为计算机术语时,是“令牌”的意思
token是计算机术语:令牌,令牌是一种能够控制站点占有媒体的特殊帧,以区别数据帧及其他控制帧。token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同的数据操作。基于 Token 的身份验证方法
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:
1.客户端使用用户名跟密码请求登录
2.服务端收到请求,去验证用户名与密码
3.验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
4.客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
5.客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
6.服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
POSIX
POSIX表示可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX ),POSIX标准定义了操作系统应该为应用程序提供的接口标准。
POSIX标准意在期望获得源代码级别的软件可移植性。换句话说,为一个POSIX兼容的操作系统编写的程序,应该可以在任何其它的POSIX操作系统(即使是来自另一个厂商)上编译执行。
简单总结:
完成同一功能,不同内核提供的系统调用(也就是一个函数)是不同的,例如创建进程,linux下是fork函数,windows下是creatprocess函数。好,我现在在linux下写一个程序,用到fork函数,那么这个程序该怎么往windows上移植?我需要把源代码里的fork通通改成creatprocess,然后重新编译…
posix标准的出现就是为了解决这个问题。linux和windows都要实现基本的posix标准,linux把fork函数封装成posix_fork(随便说的),windows把creatprocess函数也封装成posix_fork,都声明在unistd.h里。这样,程序员编写普通应用时候,只用包含unistd.h,调用posix_fork函数,程序就在源代码级别可移植了。
为什么IP数据报使用分片偏移来标识分段,而不直接采用序号
你要理解在什么情况下IP报文会进行分片。IP报文不是在发送方主机上进行分片的,而是在路由器上进行分片。
发送一个IP报文,可能经过多个路由器,两两路由器之间是不同的物理网络,这些物理网络能支持的最大报文长度(MTU)是不同的。当一个较大的报文发送到MTU较小的网络上时,路由器就会对这个报文进行分片。到了下一跳路由器不会立即对分片报文重组,因为后续还有可能经过MTU较小的网络,而是留给接受方主机进行重组。
假设报文分片时用的是序号,一个1500字节的报文发到一个MTU=620的网络上,路由器把它分成3片,序号分别是0、1、2。然后分片报文到达下一个路由器,发现下一段网络MTU=256,需要把0号分片再分成3片。这时就会发现,如果上一跳分片不是连续编号就好了,上一跳序号是0、3、6的话,现在就可以把第0片分成0、1、2三片了。
这样,如果不是用连续的序号表示分片,而是用偏移来表示,就可以完美的解决这个问题。