C#网络应用编程 第2版

第一章
1.2.网络通信模型与网络协议
1.2.1 数据通信模式
分散式、集中式与分布式
1. 分散式: 用户自己管理自己,用户之间没有信息共享和交换。
缺点:数据冗余,错乱,已淘汰。
2.集中式: 用一台计算机保存所有数据,用户通过终端【电脑等】链接,访问数据交互。
优点:较少数据冗余和不一致性。缺点:可靠性低,如果一台主机出问题,则系统瘫痪,系统相应慢。
3. 分布式
分散式和集中式系统的混合,由一个又一个连接起来的独立计算机组成。例如:
C#网络应用编程 第2版_第1张图片
1.2.2 C/S模型
在分散式、集中式、分布式基础上发展而来,把网络事务处理分为两部分。Client端,为用户提供网络请求服务的接口。Server接收用户对服务的请求并提供服务。
1.2.3 B/S模型
B/S(Browse/Server)模型,基于Web的通信模型,使用Http(Hypertext Trabsfer Protocol,超文本传送协议)通信。是一种特殊的C/S结构,特殊在这种模型的客户端是一个浏览器。
优点:每台计算机可以访问任何一个Web服务器,对用户来说只需要知道服务器的网址即可访问,而不需要针对不同的服务器分别提供专用的客户端软件。
1.2.4 P2P模型
P2P(Peer-to-Peer,对等互连,对等网络),每个联网的计算机同时运行一个应用程序的Client和Server部分。即该应用程序即起Server作用,又起Client作用。【每个客户端都想象成为一个小服务器,可以同时为其他的客户端提供服务,比如下载视频】
优点:配置容易,通信方便,成本低缺点是可靠性不如C/S模型,遭受毫克攻击的可能性高。
1.2.5 TCP/IP网络协议
TCP/IP : Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议
TCP/IP四层模型和OSI七层模型对应表 :
C#网络应用编程 第2版_第2张图片
C#网络应用编程 第2版_第3张图片
四层模型TCP/IP
应用层:
负责应用程序之间的沟通,主要协议有邮件传输协议(SMTP)、文件传输协议(FTP)、远程访问协议(Telnet)
传输层:
提供节点间的数据传输,以及应用程序之间的通信服务、主要功能数据格式化、数据确认、丢失重传等。主要协议有传输控制协议 (TCP)、用户数据报协议(UDP)等。tcp和udp给数据包(打包以后的数据)加入传输数据并把它传输到下一层中这一层负责传输数据,并且确定数 据以被送达并接收。
网际层:
提供基本的数据封包传送功能,让每一块数据包都能到达目的主机,但是不检查数据包是否被正确接收。[IP属于该层]
网络接口层:
负责接收IP数据并进行传输,从网络上接收物理帧,抽取IP 数据报 传交给下一层,对实际的网络媒体进行管理,定义如何使用 实际网络来传输数据。 数据报简单理解就是”生成报告后的数据“。【 网络接口层:如以太网设备驱动程序】
1. IP
IP数据包中含有发送它的主机地址(源地址)和接收它的主机的地址(目的地址)。
2.TCP
提供可靠的,并且无差错的通信服务。能自动调整超时的功能,因此能适应Internet的各种变化(传输时间变换不定)。
IP只保证计算机能发送和接收资料,而TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重 传。
TCP接收到数据包后,讲信息送到更高层的应用程序,服务程序和客户程序。应用程序处理后,再轮流把信息送回传输层–>网际层(设备驱动和物理介质)–>接收方。
3.UDP
UDP和TCP位于同一层,但是它不考虑数据包的顺序,错误或重发。因为udp主要用于面向查询/应答的服务。(如:NTP(网络时间协议)和DNS(域名系统).
FTP允许用户以文件操作的方式(如文件的增、删、改、查、传送等)与另一主机相互通信。
HTTP是一个简单的请求-响应协议,它通常运行在TCP之上。它指定了客户端可能发送给服务器什么样的消息以及得到什么样的响应。
OSI:开放系统互联,把通信协议抽象为七层,每层执行特定的任务,是理论的网络通信模型。TCP/IP是实际运行的网络协议。
C#网络应用编程 第2版_第4张图片

进程与线程

2.1
1.进程:
系统进行资源分配和调度的基本单位,是操作系统结构的基础。
2.线程
一个进程可以划分为若干个独立的执行流,这些独立的执行流称为线程。
2.2 进程管理类(Process类)的介绍
获取进程信息
获取本机(或远程)计算机上的进程信息、启动、关闭
2.3 线程管理类
t.Abort(): 终止线程时线程不一定会立即停止结束。因为系统在结束线程前进行代码清理工作,这样会使得线程终止比较安全。但是清理代码需要一段时间,而我们不知道需要多长时间,因此调用后工作没结束,会造成假死现象。可以在主线程中调用子线程的Join方法,并在Join方法中指定主线程等待子程序结束的等待时间。或者设置bool属性来中断防访问,再进行Abort();
所以正确停止一个线程:
77. 正确停止线程

问题: 和启动线程一样,不是想停就立刻停的。得干完手头要紧的活,比如现在在执行非托管代码,引发异常得回到托管代码中。

线程停止主要取决于工作线程是否能主动访问调用者的停止请求

标准的取消模式:协议式取消(Cooperative Cancellation)。
CancellationTokenSource cts=new CancellationTokenSource();
cts.Token.Register(fun()); //线程停止时的回调
cts.Cancel(); //发送Cancel信号 线程停止

CancellationTokenSource cts =new CancellationTokenSource();
            Thread t =new Thread(() =>
                {
                    while (true)
                    {
                        if (cts.Token.IsCancellationRequested)  【其实也是通过一个Volatile   bool  isout值属性来中断线程工作,再进行Abort()操作】
                        {
                            Console.WriteLine("线程被终止!");
                            break;
                        }
                        Console.WriteLine(DateTime.Now.ToString());
                        Thread.Sleep(1000);
                    }
                });
            t.Start();
            Console.ReadLine();
            cts.Cancel();

调用者使用CancellationTokenSource的Cancle方法通知工作线程退出。工作线程则以大致1000毫秒的频率一边工作,一边检查是否有外界传入进来的Cancel信号。若有这样的信号,则负责退出。
CancellationTokenSource。它有一个关键属性Token,Token是一个名为CancellationToken的值类型。CancellationToken继而进一步提供了布尔值的属性IsCancellationRequested作为需要取消工作的标识。CancellationToken还有一个方法尤其值得注意,那就是Register方法。

2.3.3 Volatile关键字
Volatile修饰的字段可以被多个并发执行的线程修改。该修饰符声明的字段不再被编译器优化,保证该字段在任何时候都是最新的值。
【因为编辑器优化会把代码变量可能存在寄存器中,而多线程程序中,如果把一个变量放入Cache后,又有其他线程改变了变量的值,那么本线程是无法知道这个变化的。 Volatile告诉编辑器不要对此变量进行优化】
C#网络应用编程 第2版_第5张图片
2.3.4 在一个线程中访问另一个线程的控件
在一个线程中访问另一个线程的控件委托和事件
后台线程在关闭应用时,后台线程会自动结束。

2.4 线程的优先级
注意:如果某线程优先级设置为Highest时,系统上正在运行的其他线程都会终止。

2.4.3 线程同步
线程之间存在执行先后顺序的关系。lock锁的代码段落不宜过多,造成其他线程阻塞,浪费性能。

2.4.5 线程池
适用于需要多个线程而实际执行时间又不多的场合。

第3章 IP地址转换与网卡信息检测

  1. IP

  2. 端口
    3.1.2 IP地址转换相关类
    1.IPAddress类
    C#网络应用编程 第2版_第6张图片
    2. IPEndPoint类
    3.1.3 域名解析
    IP地址虽然能够唯一标识网络上的计算机,但是它的数字很难记忆,因而用字符型的名字标识它,这个字符型地址叫做域名地址,简称域名(Domain Name)。域名转换为对于的IP地址的过程称为域名解析。
    DNS(Domain Name System,域名系统): 是因特网的一项核心服务,可以将域名和IP地址相互转换。互联网中存在装有域名系统的域名服务器,上边存放许多域名到IP地址转换的映射表。可以使得人们更加方便的访问互联网,而不用去记被机器直接读取的IP地址。

    **3.2 网卡信息与网络流量控制**
    网络适配器:又称网卡或者网络接口卡(NIC), 是连接计算机与网络的硬件设备。作用是整理计算机上发往网线上的数据,并将数据分解为适当大小的数据包之后向网络上发送。
    **3.3 网络数据编码与解码**
    
    编码:通信时,需要将字符信息转换成字节信息的过程称为编码。反之为解码
    常见的3中编码方式:
    1.ASCll字符集-->适合英语编码
    2.非ASCll字符集  -->根据自己国家的汉字提出的
    3.Unicode 字符集 -->世界上针对不同国家语言统一的编码方式,不然打开一个不知道它编码方式的文本文件,就会出现乱码。内存空间比ASCll内存占用大一倍,对能用ASCll表示的字符集来说有些浪费,所以提出了UTF(通用转换字符),根据不同的字符改变长度。
    3.3.2 Encoder和Decoder类
    	Encoder将一组字符转换为字节序列。
    	Decoder 将以编码的字节序列转为字符序列。
    	protobuf不支持二维数组
    	结构体转byte[]数组,比字符串转byte[]数组的包体大,以为字符串转byte[]时,用的UTF
    

第4章 套接字与数据流

	三次握手:	
		第一次握手,客户端发了个连接请求消息到服务端,服务端收到信息后知道自己与客户端是可以连接成功的。
		第二次握手,但此时客户端并不知道服务端是否已经接收到了它的请求,所以客户端需要得到服务端的反馈后,才确定自己与服务端是可以连接上的。服务端向客户端发送消息,客户端接收到。
		第三次握手:
		两次握手后,已经建立连接了,为什么需要第三次握手呢?
		第三次握手是为了防止已经失效的连接请求报文段突然又传到服务端,因而产生错误。
		客户端发出去的第一个连接请求由于某些原因在网络节点中滞留了导致延迟,直到**连接释放后**的某个时间点才到达服务端,假设两次握手后已经建立了连接,但是此时客户端并不能发送任何数据,而服务端还在傻傻的等候佳音,造成很大的资源浪费。所以需要第三次握手,只有客户端再次回应一下,就可以避免这种情况。
		
	在一个双方可以通信的套接字中,保存了本机和对方的IP地址和端口、以及双方通信采用的协议信息。
	套接字类型: 流套接字【实现面向连接的TCP通信】      数据报套接字【无连接的UDP通信】       原始套接字【IP数据报通信】。

在这里插入图片描述
4.1.1 面向连接的套接字

		服务器监听 、 客户端请求  、连接确认
		![在这里插入图片描述](https://img-blog.csdnimg.cn/20190711213053582.png =400x200)
		3. 关闭连接
			先用Shutdown方法停止会话,然后关闭Socket实例
			![在这里插入图片描述](https://img-blog.csdnimg.cn/20190711213659220.png =800x250)

Shutdown方法允许socket对象一直等待,直到将内部缓冲区的数据发送完为止。

4.1.2 无连接的套接字

C#网络应用编程 第2版_第7张图片
必须使用Bind方法把套接字绑定到一个本地地址和端口之后才能使用ReceiveFrom方法,如果只发送不接收则不需要绑定。
Bind():
bind 普遍遭遇的问题是试图绑定一个已经在使用的端口。该陷阱是也许没有活动的套接字存在,但仍然禁止绑定端口(bind 返回 EADDRINUSE),它由 TCP 套接字状态 TIME_WAIT 引起。该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT 状态退出之后,套接字被删除,该地址才能被重新绑定而不出问题。

4.2 数据流 文件流 内存流(封装的数据可以直接在内存中访问)
内存流:一般用于暂时缓存数据以降低程序中对临时缓冲区和临时文件的需要。虽然字节流和内存流都是保存在内存缓存区中,但是内存流可以自动增长。对长度不定的数据进行缓存,内存流方便。
三种初始化:
MemoryStream() 初始0,且长度可扩展
MemoryStream(byte[] ) 长度以定不可扩展
MemoryStream(int cap)初始大小且可以扩展 。
C#网络应用编程 第2版_第8张图片
4.2.3 网络流
必须是面向连接的。
C#网络应用编程 第2版_第9张图片

第2篇 网络协议类基本编程技术

第5章 TCP应用编程

TCP负责把用户数据按一定的格式和长度组成多个数据报进行发送,并在接收到数据报后按分解顺序重新组装和恢复用户数据。
5.1.1 TCP简介
发送时:先把数据写入TCP的发送缓冲区中,然后TCP自动从发送缓冲区中取出一定量的数据,将其组成TCP报文段逐个发送给IP层,通过IP层发出去。
接收时:从IP层接收到TCP报文段后,将其暂时保存在接收缓冲区中,程序中依次读取接收缓冲区中的数据。
.Net工作方式: 同步和异步
5.1.4 TCP的无消息边界问题
虽然TCP是发送的顺序来接收数据的,但是在传输中可能会出现不一致的情况:
eg: 发送方发了 “12345”,第二次发了“abcde”,由于TCP发送的数据没有消息边界,当收发数据包小,发送速度非常快时,接收方把几次发送的数据一起接收了,即“12345abcde”【粘包】. 另外,由于网络传输的影响,接受方可能多次才能接收到发送的消息。eg: 第一次接收"1234",第二次接收“5ab”,第三次“cde”.【拆包】
1.发送固定长度的消息,位数不足的空位补齐。
2.将消息长度与消息一起发送
在每次发送消息的消息前面用4个字节表明本次消息的长度,然后将包含消息长度的消息发送给对方;对方接收到消息后,首先从消息的前4个读取消息长度,然后根据消息长度值接收发送方发来的数据。
3.使用特殊标记分割消息
这种方法主要用于消息中不包含特殊标记的场合。例如,在每个命令后添加回车换行(\r\n)作为分割符的场合。
心跳检测步骤:
https://blog.csdn.net/G1036583997/article/details/52836859
1客户端每隔一个时间间隔发生一个探测包给服务器(一般30-40s,特殊情况6-9s)
2客户端发包时启动一个超时定时器
3服务器端接收到检测包,应该回应一个包
4如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器
5如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了

协议: Head+body
4 +1+1+1 长度+模块+ 模块中的消息数据 + 最后一个1是状态位,表示发送成或者失败【把这个状态发给客户端】
根据消息头不够再取,够了就截取转换出来,再次检查长度…
定义的数组大小,只是每次通过网卡发送的byte[]数组大小和通过网卡接收的byte[]数组大小,定义byte[]位1024

第6章 UDP应用编程

	**1.UDP和TCP的区别**
		<1. UDP速度快 
		udp不需要传输确认,因此其数据传输速度比TCP快的多。对于强调传输性能而不考虑传输完整性的应用(网络音频播放、视频点播、网络会议等)UDP更合适。
		<2.UDP有消息边界
		<3.UDP可以一对多传输
		<4.UDP可靠性不如TCP
		tcp在接收到数据后,会自动向发送方发出确认消息;接收方只有在接收到该消息时,会自动向发送方发出确认消息,发送方只有在接到确认消息后才继续发送传来的消息,否则一直等待直到收到确认消息为止。udp不提供数据保证机制。
		<5. UDP不能保证有序传输
		UDP在网络非常拥挤的情况下才会出现无序,否则很少出现
		
		局域网内的可靠广播协议,它是基于NAK的,同时采用了ACK机制来满足可靠性和一定的实时性,所以称它为混合的可靠广播协议(HRBP)。主要解决的问题 有丢包检测、失序处理和成员状态维护。它采用了滑动窗口机制来进行流量控制。
		6.3.1 广播和组播的基本概念:
		TCP仅支持一对一的传输,而且需要在传输方和接收方建立独立的通道。如果只是给很少的接收者传输数据,没问题,但实现网络会议、网上视频点播等需要大量主机发送相同的数据包,若采用单播逐个节点传输,有多少个节点就有多少次发送过程。
		广播:同时向子网中的多台计算机发送消息。
		IP: 分为两部分 网络表示部分和主机标识部分。靠子网掩码来区分,把主机标识部分二进制全部为1的地址称为本地广播地址。
		7.1 FTP:
		原理: 建立两个TCP,一个控制TCP另一个用于下载TCP数据

第8章 Http应用编程

web服务端和客户端的数据传输(图片,视频,音频)
http多线程文件下载

第11章 数据加密与解密技术

11.1.1 对称加密 和不对称加密

https://www.youtube.com/watch?v=hi8PVv2YKt4&list=PLT-_o15ZV2INAUEqsIhziCiBQemNlUVub&index=44 //youtobe课程链接
https://en.savefrom.net/ //youtobe下载
MMORPG: Massive Muti-player Online RPG 多人在线RPG
魔兽 传奇 都是MMO
总结其他游戏类:
RPG:Role Playing Game角色扮演游戏
SLG:Simulation Game模拟/战略游戏
ACT:Action 动作游戏
AVG:Adventure Game冒险游戏
FPS:First Person Shooting第一人称射击游戏 FTG:Fighting Game格斗游戏
RAC:Racing 赛车游戏
SPG:Sports Game 体育类游戏
RTS:Real Time Strategy即时战略游戏
STG:Shooting Game射击游戏
MUG:Music Game 音乐游戏
PUZ:Puzzle 益智游戏
TAB:Table 桌面类游戏
ETC:ETC 其它类游戏

状态同步 3-5s同步 ->由服务器计算 MMORPG
检测网络–>掉线后–>重连
帧同步–>
逻辑帧 网络帧50–60
同步策略:
lock step: 等待其他客户端 一卡都卡 优化==》a通知行走服务器,这时a不理会自身是收到的消息不然就弹回来了。这种方式网速慢会有差异(1s延迟)
乐观锁:50ms 时间到了后,不等待其他客户端.moba
网游戏数据存储:
C#网络应用编程 第2版_第10张图片
一般手游的划分:
手游服务器只是一个功能方面的划分,而不是物理上的划分。
C#网络应用编程 第2版_第11张图片
对于lol: 在物理上也进行了服务器的划分:
C#网络应用编程 第2版_第12张图片
lol服务器协议定制:
C#网络应用编程 第2版_第13张图片
高低字节序问题:

1.大小端我知道,可是什么时候需要转换呢?
答:网络通信中默认的字节序是大端的。而C#在windows平台上是小端字节序。而且要注意客户端和服务器字节序是否一致的问题
另外c#直接提供了网络字节序转换方法。
System.Net.IPAddress.HostToNetworkOrder(本机到网络转换)
System.Net.IPAddress.NetworkToHostOrder(网络字节转成本机)
推荐使用这种方法,简单有效。
代码示例:
short x = 6;
short b = System.Net.IPAddress.HostToNetworkOrder(x); //把x转成相应的大端字节数
byte[] bb = System.BitConverter.GetBytes(b);//这样直接取到的就是大端字节序字节数组。
对于字符串型:使用 System.Text.Encoding.Default.GetBytes();直接取字串对应字节数组。(因为字符串型是以一个字节为单位的,所以不存在大小端问题)
1.网络传数据的时候是一个字节一个字节的传.字符串里的每一个字符只用一个字节,前面的就先传,接收的后再解释的时候也是按顺序来,所以字符串没有网络字节序的分别.
2.网络字节序默认是大端,也就是说任何机器如果收到一个int型的4个字节,那么这个机器就会认为第一个字节是最高位,最后一个字节是最低位。

计算机硬件有两种储存数据的方式:大端字节序(big endian)和小端字节序(little endian)。
举例来说,数值0x2211使用两个字节储存:高位字节是0x22,低位字节是0x11。
•大端字节序:高位字节在前,低位字节在后,这是人类读写数值的方法。
•小端字节序:低位字节在前,高位字节在后,即以0x1122形式储存。

我一直不理解,为什么要有字节序,每次读写都要区分,多麻烦!统一使用大端字节序,不是更方便吗?
上周,我读到了一篇文章,解答了所有的疑问。而且,我发现原来的理解是错的,字节序其实很简单。

首先,为什么会有小端字节序?
答案是,计算机电路先处理低位字节,效率比较高,因为计算都是从低位开始的。所以,计算机的内部处理都是小端字节序。
但是,人类还是习惯读写大端字节序。所以,除了计算机的内部处理,其他的场合几乎都是大端字节序,比如网络传输和文件储存。

计算机处理字节序的时候,不知道什么是高位字节,什么是低位字节。它只知道按顺序读取字节,先读第一个字节,再读第二个字节。
如果是大端字节序,先读到的就是高位字节,后读到的就是低位字节。小端字节序正好相反。
理解这一点,才能理解计算机如何处理字节序。

字节序的处理,就是一句话:
“只有读取的时候,才必须区分字节序,其他情况都不用考虑。”
处理器读取外部数据的时候,必须知道数据的字节序,将其转成正确的值。然后,就正常使用这个值,完全不用再考虑字节序。
即使是向外部设备写入数据,也不用考虑字节序,正常写入一个值即可。外部设备会自己处理字节序的问题。

不同cpu平台上字节序通常也不一样。

手机比例: 960*640

1.服务器socket监听
2. 创建用户池
用户对象
3. 监听当前服务器网卡所有可用IP地址的port。 外网
//Semaphore:
//是操作系统维持的一个整数。当整数位0时。其他线程无法进入。当整数大于0时,线程可以进入。每当一个线程进入,整数-1,线程退出后整数+1。整数不能超过信号量的最大请求数。

//AcceptAsync
//如果 I/O 操作挂起(没空则排队执行),将返回 true。操作完成时,将引发 context 参数的 SocketAsyncEventArgs…::.Completed 事件。
//如果 I/O 操作同步完成(正好有空直接执行),将返回 false。将不会引发 context 参数的 SocketAsyncEventArgs…::.Completed 事件,并且可能在方法调用返回后立即检查作为参数传递的 context 对象以检索操作的结果

你可能感兴趣的:(network)