我的解决方案

CodingK_Session

聊聊网络

基础

起源

起源于1969年美国国防部的军用项目,最初只是一个单个的分组交换网ARPANET(并不是一个互连的网络)。1983年TCP/IP协议成为ARPANET上的标准协议,使所有使用 TCP/IP协议 的计算机都能利用互连网相互通信。因此1983年被当作因特网(Internet)诞生的时间。之后经过不断发展,形成了如今的英特网(Internet)。

网络通信是指什么?

计算设备之间通过网络交换数据,更通俗地说法就是:主机A上的某个程序(进程)与主机B上的某个程序(进程)进行数据交换。

网络通信如何实现?

计算设备之间通过共同遵守的 网络协议(network protocol) ,以约定好的规则来交换数据。

计算机网络体系结构

五层协议的体系结构

OSI七层协议:概念清楚,理论完整,但它复杂不实用。

TCP/IP四层协议:应用非常广泛。实质上,TCP/IP只有上面三层,最下层的网络接口层并没有什么具体内容。

综合前面两者,我们一般采用五层协议的体系结构来学习理解计算机网络原理。

五层协议功能划分

应用层:直接为用户的应用进程提供服务。这一层的协议很多,比如HTTP协议(浏览器)、SMTP协议(邮件)、FTP协议(文件传输)等。

运输层:运输应用层的数据,多个应用进程可同时使用运输层的服务,以及分发运输层的信息到应用层中相应的进程上。运输层主要使用两种协议:

  • 传输控制协议TCP(Transmission Control Protocol): 面向连接 ,以报文段(segment)为传输单位,保证传输的可靠性。

  • 用户数据报协议UDP(User Datagram Protocol): 无连接 以用户数据报为传输单位,不保证传输的可靠性。

网络层:把运输层的报文段或用户数据报封装成 分组或包 进行传送。网络层使用IP协议,因此分组也叫作 IP数据报 ,简称数据报。此外网络层还要选择合适的路由,使运输层里的数据通过网络中的路由器找到目的主机。

数据链路层:数据在网络上传输时总是在一段一段的链路上传送的(主机和路由器之间或者两个路由器之间),这时需要链接层的协议将网络层交下来的IP数据报组装成 帧(framing) ,以便在相邻的链路之间传送。数据帧里包含了必要的 传输控制信息 。

物理层:在物体层上所传数据就是比特流。用不同的电压代表「0」或「1」,在硬件设备上实现数据传输。

注意:现在我们常提到的TCP/IP并不一定单指TCP和IP两个具体的协议,而是指组成因特网时所使用的整个 TCP/IP协议族 (protocol suite),还包括了其它协议,比如:DNS协议(域名转换为IP地址)、ARP协议(IP地址转换为mac地址)等等。

TCP对比UDP

简易TCP通信案例

TCP所谓的建立连接并不是在物理层面建立什么连接,而是通过在通信两端建立一定的数据结构来维护双方交互的状态,用这样的数据结构来保证所谓的面向连接的特性,实现可靠传输。

简易UDP通信案例

UDP在局域网基本不会丢包,很多内网的服务都是用UDP开发,简单高效易用。

实现

在.net core使用以下2个包实现TCP/UDP通信,1个包实现指定数据流格式。

1
2
3
using System.Net;
using System.Net.Sockets;
using System.Text;

个人简易demo源码(UDP、TCP):

实现帧同步网络库

作为HOK demo的工具组之一。

为什么使用UDP

使用帧同步需要非常频繁交互。UDP更快,没有TCP那么繁琐的机制和包头额外数据。

KCP入门

一套高效确认算法,可以让数据传输变得可靠有序 。

KCP源码

源码地址,手册很细致,里面也有一些原理性质的概念。

C#版本

思路

会话ID必须由服务器统一分配,不可重复。

实现模拟连接以便识别不同客户端数据。

双端复用代码,抽象网络会话类,进行数据收发。

demo

在NuGet市场上就有,不用非去github下源码。

基于KCP实现的可靠UDP通信

发番协定

初次连接,传4个空字节过去。

当服务端收到后知道是新客户端,就生成全局唯一uuid并返回,返回的形式是“4个空字节+uuid”。客户端收到后设置KCPSession的sid。

kcp添加控制信息的包里,头4个字节的数字对应传入的int值,每一个字节可以转化为对应的0~255的数字。而4个字节刚好对应一个uint32,也就是传入new Kcp(sid, m_handle)的sid。

心跳机制

客户端和服务端分别实现Session,两边通用一样的结构(KCPNet),但是用不一样的遍历逻辑(ClientSession、ServerSession)和管理层(ClientStart、ServerStart)。

客户端会定期发送Ping Message到服务端。

服务端有一个字典存放所有的Session,也就是ServerSession类型,超过设定时长未收到来自客户端传来的消息,就在本地字典内清除这个客户端的信息。

基于KCPNet的解决方案

本人基于KCPNet项目,集成proto协议、KCP算法的 Unity客户端 +.net core/framework服务端 解决方案。

CodingK_Session

教程就不写了,我在里面写了2个使用案例。