简介

工作中经常遇到需要实现TCP客户端或服务端的时候,如果每次都自己写会很麻烦且无聊,使用SuperSocket库又太大了。这时候就可以使用SimpleTCP了,当然仅限于C#语言。

SimpleTCP是一个简单且非常有用的 .NET 库,用于处理启动和使用 TCP 套接字(客户端和服务器)的重复性任务,使用起来非常方便、代码也少。它的内部不是直接使用的Socket,而是在TcpClient的基础上进行了再次封装,接口更简单、明了。

它的主要特点如下:

  • 源码简单:源码就几个类,每个类也不大,在了解TcpClient用法的基础上不需要注释就可以看懂。
  • 功能单一:不像其它库一样功能繁多,它只专注于实现简单的TCP客户端、服务端,使用起来不用担心增加系统的复杂性。
  • 使用简单:后面的示例会具体讲解,启动一个客户端或服务端只需要几行代码,想扩展功能也很简单。

说一下它的不足之处(在我看来完全可以接受):

  • 已停止更新:最后更新时间是2017年,不过库的功能比较简单、单一,也没那么多更新的内容。
  • 性能不是最优的:底层是基于TcpClient的,性能注定不会太高,但能用TcpClient的地方都可以用它。

使用方法

在项目中直接引用SimpleTCP.dll即可, dll文件可以通过NuGet安装或从github下载源码编译。

SimpleTCP内部有一个特殊字符分割字符串的协议可以直接使用,也可以在DataReceived事件处理程序中实现自己的协议。

实现客户端

实现一个客户端的代码如下:

//初始化
var client = new SimpleTcpClient(); //设置编码格式,默认是UTF8
client.StringEncoder = System.Text.ASCIIEncoding.ASCII;
//设置分隔符,默认是0x13
client.Delimiter = Encoding.ASCII.GetBytes("\r")[0]; //收到分割数据的事件,遇到分隔符就会触发事件
client.DelimiterDataReceived += (sender, msg) =>
{
Console.WriteLine("DelimiterStr-"+DateTime.Now.ToString()+ msg.MessageString);
}; //收到数据的事件,可以在这里实现自己的协议
client.DataReceived += (sender, msg) =>
{
//字节数组
Console.WriteLine("Data:"+BitConverter.ToString(msg.Data));
//字符串消息
Console.WriteLine("ReceivedStr:" + msg.MessageString);
};

DelimiterDataReceivedDataReceived内部使用了两个不同的字节链表,解析起来互不影响。这两个事件的处理程序中尽量不要做耗时的操作,否则会影响后续的数据接收

SimpleTCP没有心跳、重连功能,也没找到反馈客户端连接状态的属性(不建议使用内部TcpClient的连接状态)。我们可以直接扩展这些功能,代码如下:

bool exit = false;
bool connected = false;
Task.Factory.StartNew(() =>
{
while (!exit)
{
try
{
if (connected)
{
//发送心跳
client.Write("");
Task.Delay(10000).Wait();
}
else
{
//断线重连
client.Connect("127.0.0.1", 4196);
connected = true;
Task.Delay(1000).Wait();
}
}
catch (Exception)
{
connected = false;
client.Disconnect();
}
} }, TaskCreationOptions.LongRunning);

把上面的代码按顺序复制到控制台的Main函数中,然后加入下面的代码就可以收发数据了:

while (true)
{
string strLine = Console.ReadLine();
if (strLine == "esc")
{
exit = true;
client.Disconnect();
return;
}
if (connected)
{
//获取服务端回复的消息,最多等待3秒,收到消息时会提前返回
//也可以使用Write、WriteLine方法发送数据,WriteLine会自动在后面加上设置的分隔符
var replyMsg = client.WriteLineAndGetReply(strLine, TimeSpan.FromSeconds(3));
if (replyMsg != null)
{
Console.WriteLine(replyMsg);
}
}
}

注:WriteLineAndGetReply内部使用的是DataReceived,不会自动去除分隔符

实现服务端

服务端功能比较简单,把收到分割数据加工后返回客户端,代码如下:

//初始化
var server = new SimpleTcpServer();
//设置编码格式,默认是UTF8
server.StringEncoder = System.Text.ASCIIEncoding.ASCII;
server.Delimiter = Encoding.ASCII.GetBytes("\r")[0]; //分割数据接收事件
server.DelimiterDataReceived += (sender, msg) =>
{
Console.WriteLine(msg.TcpClient.Client.RemoteEndPoint.ToString()+":" + msg.MessageString);
msg.ReplyLine("Reply-" + msg.MessageString);
}; //数据接收数据
server.DataReceived += (sender, msg) =>
{
Console.WriteLine(msg.TcpClient.Client.RemoteEndPoint.ToString() + ":" + msg.MessageString);
}; //客户端连接事件
server.ClientConnected += (sender, msg) =>
{
Console.WriteLine("ClientConnected:" + msg.Client.RemoteEndPoint.ToString());
}; //客户端断开事件
server.ClientDisconnected += (sender, msg) =>
{
Console.WriteLine("ClientDisconnected:" + msg.Client.RemoteEndPoint.ToString());
}; //开始监听
server.Start(4196);
//监听的IP
var listeningIps = server.GetListeningIPs();
//监听的V4Ip
var listeningV4Ips = server.GetListeningIPs().Where(ip => ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork); Task.Factory.StartNew(() =>
{
while (true)
{
//连接数监控
int clientsConnected = server.ConnectedClientsCount;
Console.WriteLine("当前连接的客户端数:" + clientsConnected);
Task.Delay(10000).Wait();
} }, TaskCreationOptions.LongRunning);
Console.ReadLine(); //停止监听
server.Stop();
Console.WriteLine("停止服务端!");
Console.ReadLine();

总结

上面的代码主要为了展示库的功能,实际使用时可能就几行代码,性能要求不高的项目都可以使用。

项目和库的源码链接如下:

C#开源类库SimpleTCP的更多相关文章

  1. Atitit java onvif 开源类库 getProfiles getStreamUri

    Atitit java onvif 开源类库 getProfiles getStreamUri 1. ONVIF Java Library by Milgo1 1.1. https://github. ...

  2. 一些iOS高效开源类库

    因为iOS SDK相对比较底层,所以开发者就得受累多做一些体力活.不过幸运的是,有很多第三方的类库可以用来简化很多不必要的工作.笔者整理了一下在本人学习过程中用到的一些比较有用Objective-C开 ...

  3. dropzonejs中文翻译手册 DropzoneJS是一个提供文件拖拽上传并且提供图片预览的开源类库.

    http://wxb.github.io/dropzonejs.com.zh-CN/dropzonezh-CN/ 由于项目需要,完成一个web的图片拖拽上传,也就顺便学习和了解了一下前端的比较新的技术 ...

  4. [转]C#常用开源类库收集

    .net PDF 类库 PDFsharp PDFsharp是一款可以让.NET框架支持的任何语言很容易的创建PDF文件的类库. ASP.NET FO PDF FO PDF 是一款C#编写类似于ASP. ...

  5. C#常用开源类库

    一.AOP框架        Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase 独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种 ...

  6. Json序列化之.NET开源类库Newtonsoft.Json的研究

     一.Json简介 JSON(全称为JavaScript Object Notation) 是一种轻量级的数据交换格式.它是基于JavaScript语法标准的一个子集. JSON采用完全独立于语言的文 ...

  7. 【转】java开源类库pinyin4j的使用

    最近CMS系统为了增加查询的匹配率,需要增加拼音检索字段,在网上找到了pinyin4j的java开源类库,提供中文转汉语拼音(并且支持多音字), 呵呵,看了看他的demo,决定就用它了,因为我在实际使 ...

  8. 使用CocoaPods管理第三方开源类库

    iOS开发中经常会用到许多第三方开源类库,比如AFNetworking.FMDB.JSONKit等等,使用CocoaPods这个工具就能很方便得对工程中用到的类库进行管理,包括自动下载配置以及更新. ...

  9. Java 的 JSON 开源类库选择比较(zz)

    在看了作者的介绍,然后我又到mvnrepository上去看了各个库的的使用数之后,发现只能在jackson和gson之间做选择. 以下是原文 有效选择七个关于Java的JSON开源类库 April  ...

随机推荐

  1. leetcode 有效三角形的个数

    题目描述: 平明伞兵解法: 既然要求满足三角形要求的三边,简单来说,就是最短两边之和大于第三边,所以,第一步Arrays.sort().先排序,然后直接伞兵暴力法,三重循环.当然最后肯定是能跑出来的, ...

  2. 【Azure 应用服务】Azure Function HTTP 触发后, 230秒就超时。而其他方式触发的Function, 执行5分钟后也超时,如何调整超时时间?

    问题描述 Azure Function HTTP 触发后, 230秒就超时,而其他方式触发的Function, 执行5分钟后也超时,如何调整超时时间? 问题分析 查阅官方文档,对函数应用超时持续时间有 ...

  3. Vue学习笔记(一)简单使用和插值操作

    目录 一.Vue是什么 二.Vue简单体验 1. 声明式渲染 2. vue列表展示 3. 处理用户输入(事件监听) 三.插值操作 1. Mustache语法 2. 常用v-指令 v-once v-ht ...

  4. Android 开发学习进程0.33 横竖屏切换

    安卓横竖屏大多数已经在manifest文件中将activity使用android:screenOrientation="portrait"属性写死,如简单的界面切换可直接更改为&q ...

  5. Nacos 权限控制介绍及实战

    方案背景 Nacos自开源依赖,权限控制一直需求比较强烈,这也反应了用户需求将Nacos部署到生产环境的需求.最新发布的Nacos 1.2.0版本已经支持了服务发现和配置管理的权限控制,保障用户安全上 ...

  6. Guava入门第一章(Joiner)

    Guava是什么? Guava是一种基于开源的Java库,Google Guava源于2007年的"Google Collections Library".这个库是为了方便编码,并 ...

  7. CVE-2020-17523:Apache Shiro身份认证绕过漏洞分析

    0x01 Apache Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授权.密码和会话管理. 0x02 漏洞简介 2021年2月1日,Apache Shiro官 ...

  8. Linux 进程间传递文件描述符

    文章目录 文件描述符 文件数据结构 共享文件 UNIX域socket实现传递文件描述符 进程间传递打开的文件描述符,并不是传递文件描述符的值.先说一下文件描述符. 文件描述符 对内核来说,所有打开的文 ...

  9. NOIP 模拟 $24\; \rm matrix$

    题解 \(by\;zj\varphi\) 发现 \(\rm n,m\) 都很小,考虑分行状压. 但是上一行和下一行的按钮状态会对当前行造成影响,所以再枚举一个上一行的按钮状态. 因为对于两行,只有如下 ...

  10. JavaScript(Node.js)+ Selenium 实现淘宝抢单

    JavaScript(Node.js)+ Selenium 淘宝抢单 为了买买买我也是拼了,看了一点selenium的资料,随便写的. 程序写的比较烂,但是够我自己用了,望各路大牛指教. 使用说明: ...