zy-leon / MNetSocket-CSharp

本项目是一个只有6个C#代码文件的开源小工程,用来学习基于TCP的套接字通信包,可以自定义通信协议,处理分包和粘包,内置一个服务端和客户端的套接字程序,也有测试代码和对应的博客讲解代码。整个工程基本基于良好的面向对象**,代码注释清晰简洁。

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MNetSocket-Python

[TOC]

一、项目简介

本项目是一个只有6个C#代码文件的开源小工程,用来学习基于TCP的套接字通信包,可以自定义通信协议,处理分包和粘包,内置一个服务端和客户端的套接字程序,也有测试代码和对应的博客讲解代码。整个工程基本基于良好的面向对象**,代码注释清晰简洁。

1、项目目录结构

这个小项目共有6个C#代码文件代码,各自作用如下:

image-20210408214923795

2、项目代码功能

这个小项目共有6个C#代码文件代码,各自作用如下:

模块 脚本名称 主要功能
核心 MsgProtol.cs 提供服务端和客户端的通信协议
ServerSocket.cs 提供服务端TCP套接字通信功能的接口
ClientSocket.cs 提供客户端TCP套接字通信功能的接口
测试 TestServer.cs 基于Unity环境测试ServerSocket提供的接口
TestClient.cs 基于Unity环境测试ClientSocket提供的接口
工具 DebugHelper.cs 基于Unity环境的日志调试工具,提供自定义颜色功能

3、项目主要特色

(1)本项目提供了一个自定义通信协议类MsgProtol,该类封装了C#语言的打包和解包方法,可以解决分包和粘包问题,也可以根据自己需求更改消息头设置,原来参考Python编程——基于TCP的套接字通信包【开源】

(2)本项目提供了不局限于unity环境的C#的套接字封装类,测试代码基于Unity环境,用户也可以经过简单修改使其适用于其他C#开发环境。

(3)本项目借助Json格式编码不仅可以传输字符串信息,也实现实现了类对象的参数化传输,例如:

img点击并拖拽以移动

(4)本项目的注释和封装都较好,还有对应的博客讲解,是基于TCP的套接字开发的较好学习材料。

4、项目主要不足

由于这只是作者的一个小型演示项目,并没有进行更多完善,必然存在一些不足,作者目前已经发现的一些可扩展的地方如下:

(1)本项目的自定义通信协议类MsgProtol不支持包含中文字符的消息打包和解包,这主要是因为json解码时无法解码包含中文字符,如果读者找到了较好的解决方案,欢迎留言共同学习。

(2)本项目提供了服务端的广播功能演示,并没有开发针对特定客户端的发送和接收的API接口,但是这也不困难,我这里简单说下其中一种简单的实现思路:

(1)在通信协议的消息头部分(源码中是3个数字部分)中新增一个数字来记录消息发送方的身份ID(可以自己设计,最简单是随机码)

(2)服务端接收到客户端连接时第一次接收到信息记录下身份ID,根据不同身份ID就可针对不同客户端发送消息。

(3)本文没有使用多线程来处理客户端的消息接收,这个处理起来其实也并不困难。

(4)本文没有测试多个客户端连接的效果,因为作者的项目中暂时不需要,要想进一步升级也并不困难。

综合来讲,本项目无法代替大型专业的TCP通信包,在大型项目中可能功能有限,但是由于其代码便于理解,适合帮助开发者学习如何构建自己的个性化需求的TCP通信包

二、背景知识

基于TCP的套接字通信是深入学习C#程序的必备技能之一,套接字不仅可以用于网络编程,在本地不同进程之间的通信不同编程语言的程序通信中也应用十分广泛。 本篇文章是在之前了解套接字编程接口的基础上进一步扩展,写出一套真正可用于实际程序通信的代码。本项目会集中研究套接字通信中的分包和粘包问题自定义通信协议的方法,方便入门套接字的同学进阶。

完整的项目开源信息如下:

MNetSocket-CSharp 基于C#的网络通信包
开发者 MRL Liu
编程语言 C#
项目描述 基于TCP的套接字通信包,可以自定义通信协议,处理分包和粘包
对应博客1 https://blog.csdn.net/qq_41959920/article/details/115380403
对应博客2 https://blog.csdn.net/qq_41959920/article/details/115529675
GitHub https://github.com/MagicDeveloperDRL/MNetSocket-CSharp
参考博客 https://blog.csdn.net/yannanxiu/article/details/52096465

三、项目研究问题

众所周知,套接字是主流语言提供的用于进行网络进程通信的程序接口,其中最常见的是基于TCP协议的套接字编程,基于TCP协议的套接字可以保证:

**可靠传播。**在一般情况下,数据传输过程中数据不会发生丢失,并且数据发送和接收的顺序不会改变,即我发送一个“Hello”和“World”,对方一定会按顺序先后收到“Hello”和“World”。

**数据可靠。**在一般情况下,数据传输过程中无论数据包被如何组合拆分等,都不会添加与发送信息无关的无效信息,即数据不会被污染,按照指定编码方式进行解码即可还原原来的信息。

但是在实际进行TCP编程的过程中,如果使用原生的套接字接口,在处理消息通信时,需要处理以下两个典型问题:

1、分包和粘包问题

(1)分包问题

TCP是以(Segment)为单位发送数据的,建立TCP链接后,有一个最大消息长度(MSS)。如果应用层数据包超过MSS,就会把应用层数据包拆分,分成两个段来发送。这个时候接收端的应用层就要拼接这两个TCP包,才能正确处理数据。

简单理解,分包现象就是一次传输的数据过多时,TCP协议会自动将本次的数据拆分成多个消息包进行发送。

例如,发送方发送字符串”helloworld”,接收方却接收到了两个字符串”hello”和”world”。

(2)粘包问题

在某些特殊环境下,TCP为了提高网络的利用率,会使用一个叫做Nagle的算法。该算法是指,发送端即使有要发送的数据,如果很少的话,会延迟发送。如果应用层给TCP传送数据很快的话,就会把两个应用层数据包“粘”在一起,TCP最后只发一个TCP数据包给接收端。

简单理解,粘包现象就是当网络繁忙时,TCP协议会将多份小的消息包打包成一个消息包进行发送。

例如,发送方发送两个字符串”hello”+”world”,接收方却一次性接收到了”helloworld”。

2、自定义通信协议

TCP套接字可以提供基本的字符串类型的信息传输,但是字符串可以代表什么含义,怎么解释它需要开发者来自定义。更重要的是,为了解决分包和粘包问题,我们也必须自定义一个简单的通信协议。

通信协议听起来很高大上,其实本质上就是发送方接收方达成的约定,对每个完整的消息包格式做出规定,接收数据时按照这个格式进行检查,从而得到一个个正确的消息包。

最简单的消息格式就是我们在消息正文的前方加入一个固定长度的数字表示消息正文的长度,这样就可以基本解决分包和粘包问题。

但是为了之后可以判断我们的消息类型,也为了便于设计客户端和服务端,我们这里稍微复杂一点,即本文定义的消息格式如下:

消息头 消息正文
正文长度(bodySize) 指令类型(cmd) 是否回复(recv) 正文
无符号32位整型变量 无符号32位整型变量 无符号32位整型变量 ——
4字节 4字节 4字节 ——

本人博客会详细介绍如何实现上述设计。

About

本项目是一个只有6个C#代码文件的开源小工程,用来学习基于TCP的套接字通信包,可以自定义通信协议,处理分包和粘包,内置一个服务端和客户端的套接字程序,也有测试代码和对应的博客讲解代码。整个工程基本基于良好的面向对象**,代码注释清晰简洁。


Languages

Language:C# 100.0%