目錄
* 簡介 <https://www.cnblogs.com/coldairarrow/p/11336771.html#%E7%AE%80%E4%BB%8B>
* 產(chǎn)生背景
<https://www.cnblogs.com/coldairarrow/p/11336771.html#%E4%BA%A7%E7%94%9F%E8%83%8C%E6%99%AF>
* 使用方式
<https://www.cnblogs.com/coldairarrow/p/11336771.html#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F>
* TcpSocket <https://www.cnblogs.com/coldairarrow/p/11336771.html#TcpSocket>
* WebSocket <https://www.cnblogs.com/coldairarrow/p/11336771.html#WebSocket>
* UdpSocket <https://www.cnblogs.com/coldairarrow/p/11336771.html#UdpSocket>
* 結尾 <https://www.cnblogs.com/coldairarrow/p/11336771.html#%E7%BB%93%E5%B0%BE>
簡介
DotNettySocket是一個.NET跨平臺Socket框架(支持.NET4.5+及.NET
Standard2.0+),同時支持TcpSocket、WebSocket和UdpSocket,其基于微軟強大的DotNetty框架,力求為Socket通訊提供
簡單、高效、優(yōu)雅的操作方式。
安裝方式:Nuget安裝DotNettySocket即可
項目地址:https://github.com/Coldairarrow/DotNettySocket
<https://github.com/Coldairarrow/DotNettySocket>
產(chǎn)生背景
兩年前最開始接觸物聯(lián)網(wǎng)的時候,需要用到Tcp及Udp通訊,為了方便使用,將原始的Socket進行了簡單的封裝,基本滿足了需求,并將框架開源。但是由于精力及實力有限,沒有進一步優(yōu)化原框架。后來發(fā)現(xiàn)了強大的DotNetty框架,DotNetty是微軟Azure團隊開源基于Java
Netty框架的移植版,其性能優(yōu)異、維護團隊強大,許多.NET強大的框架都使用它。DotNetty功能強大,但是用起來還是不夠簡潔(或許是個人感覺),剛好最近項目需要用到WebSocket,因此鄙人抽時間基于DotNetty進行簡單封裝了下,擼出一個力求
簡單、高效、優(yōu)雅的Socket框架。
使用方式
TcpSocket
Tcp是面向連接的,所以服務端對連接的管理就至關重要,框架支持各種事件的處理、給連接設置連接名(身份標識)、通過連接名找到特定連接、連接收發(fā)數(shù)據(jù)、分包、粘包處理。
* 服務端 using Coldairarrow.DotNettySocket; using System; using System.Text;
using System.Threading.Tasks; namespace TcpSocket.Server { class Program {
static async Task Main(string[] args) { var theServer = await
SocketBuilderFactory.GetTcpSocketServerBuilder(6001) .SetLengthFieldEncoder(2)
.SetLengthFieldDecoder(ushort.MaxValue, 0, 2, 0, 2) .OnConnectionClose((server,
connection) => {
Console.WriteLine($"連接關閉,連接名[{connection.ConnectionName}],當前連接數(shù):{server.GetConnectionCount()}");
}) .OnException(ex => { Console.WriteLine($"服務端異常:{ex.Message}"); })
.OnNewConnection((server, connection) => { connection.ConnectionName =
$"名字{connection.ConnectionId}";
Console.WriteLine($"新的連接:{connection.ConnectionName},當前連接數(shù):{server.GetConnectionCount()}");
}) .OnRecieve((server, connection, bytes) => {
Console.WriteLine($"服務端:數(shù)據(jù){Encoding.UTF8.GetString(bytes)}");
connection.Send(bytes); }) .OnSend((server, connection, bytes) => {
Console.WriteLine($"向連接名[{connection.ConnectionName}]發(fā)送數(shù)據(jù):{Encoding.UTF8.GetString(bytes)}");
}) .OnServerStarted(server => { Console.WriteLine($"服務啟動"); }).BuildAsync();
Console.ReadLine(); } } }
* 客戶端 using Coldairarrow.DotNettySocket; using System; using System.Net;
using System.Text; using System.Threading.Tasks; namespace UdpSocket.Client {
class Program { static async Task Main(string[] args) { var theClient = await
SocketBuilderFactory.GetUdpSocketBuilder() .OnClose(server => {
Console.WriteLine($"客戶端關閉"); }) .OnException(ex => {
Console.WriteLine($"客戶端異常:{ex.Message}"); }) .OnRecieve((server, point, bytes)
=> {
Console.WriteLine($"客戶端:收到來自[{point.ToString()}]數(shù)據(jù):{Encoding.UTF8.GetString(bytes)}");
}) .OnSend((server, point, bytes) => {
Console.WriteLine($"客戶端發(fā)送數(shù)據(jù):目標[{point.ToString()}]數(shù)據(jù):{Encoding.UTF8.GetString(bytes)}");
}) .OnStarted(server => { Console.WriteLine($"客戶端啟動"); }).BuildAsync(); while
(true) { await theClient.Send(Guid.NewGuid().ToString(), new
IPEndPoint(IPAddress.Parse("127.0.0.1"), 6003)); await Task.Delay(1000); } } } }
WebSocket
WebSocket與TcpSocket接口基本保持一致,僅有的區(qū)別就是TcpSocket支持字節(jié)的收發(fā)并且需要自行處理分包粘包。而WebSocket直接收發(fā)字符串(UTF-8)編碼,并且無需考慮分包粘包??蚣苣壳皼]有支持WSS,建議解決方案是使用Nginx轉(zhuǎn)發(fā)即可(相關資料一搜便有)
* 服務端 using Coldairarrow.DotNettySocket; using System; using
System.Threading.Tasks; namespace WebSocket.Server { class Program { static
async Task Main(string[] args) { var theServer = await
SocketBuilderFactory.GetWebSocketServerBuilder(6002)
.OnConnectionClose((server, connection) => {
Console.WriteLine($"連接關閉,連接名[{connection.ConnectionName}],當前連接數(shù):{server.GetConnectionCount()}");
}) .OnException(ex => { Console.WriteLine($"服務端異常:{ex.Message}"); })
.OnNewConnection((server, connection) => { connection.ConnectionName =
$"名字{connection.ConnectionId}";
Console.WriteLine($"新的連接:{connection.ConnectionName},當前連接數(shù):{server.GetConnectionCount()}");
}) .OnRecieve((server, connection, msg) => { Console.WriteLine($"服務端:數(shù)據(jù){msg}");
connection.Send(msg); }) .OnSend((server, connection, msg) => {
Console.WriteLine($"向連接名[{connection.ConnectionName}]發(fā)送數(shù)據(jù):{msg}"); })
.OnServerStarted(server => { Console.WriteLine($"服務啟動"); }).BuildAsync();
Console.ReadLine(); } } }
* 控制臺客戶端 using Coldairarrow.DotNettySocket; using System; using
System.Threading.Tasks; namespace WebSocket.ConsoleClient { class Program {
static async Task Main(string[] args) { var theClient = await
SocketBuilderFactory.GetWebSocketClientBuilder("127.0.0.1", 6002)
.OnClientStarted(client => { Console.WriteLine($"客戶端啟動"); })
.OnClientClose(client => { Console.WriteLine($"客戶端關閉"); }) .OnException(ex => {
Console.WriteLine($"異常:{ex.Message}"); }) .OnRecieve((client, msg) => {
Console.WriteLine($"客戶端:收到數(shù)據(jù):{msg}"); }) .OnSend((client, msg) => {
Console.WriteLine($"客戶端:發(fā)送數(shù)據(jù):{msg}"); }) .BuildAsync(); while (true) { await
theClient.Send(Guid.NewGuid().ToString()); await Task.Delay(1000); } } } }
* 網(wǎng)頁客戶端 <!DOCTYPE HTML> <html> <head> <meta charset="utf-8">
<title>菜鳥教程(runoob.com)</title> <script type="text/javascript"> function
WebSocketTest() { if ("WebSocket" in window) { var ws = new
WebSocket("ws://127.0.0.1:6002"); ws.onopen = function () {
console.log('連上服務端'); setInterval(function () { ws.send("111111"); }, 1000); };
ws.onmessage = function (evt) { var received_msg = evt.data; console.log('收到' +
received_msg); }; ws.onclose = function () { console.log("連接已關閉..."); }; } else
{ alert("您的瀏覽器不支持 WebSocket!"); } } </script> </head> <body> <div id="sse"> <a
href="javascript:WebSocketTest()">運行 WebSocket</a> </div> </body> </html>
UdpSocket
Udp天生便是收發(fā)一體的,以下分為服務端與客戶端僅僅是為了方便理解
* 服務端 using Coldairarrow.DotNettySocket; using System; using System.Text;
using System.Threading.Tasks; namespace UdpSocket.Server { class Program {
static async Task Main(string[] args) { var theServer = await
SocketBuilderFactory.GetUdpSocketBuilder(6003) .OnClose(server => {
Console.WriteLine($"服務端關閉"); }) .OnException(ex => {
Console.WriteLine($"服務端異常:{ex.Message}"); }) .OnRecieve((server, point, bytes)
=> {
Console.WriteLine($"服務端:收到來自[{point.ToString()}]數(shù)據(jù):{Encoding.UTF8.GetString(bytes)}");
server.Send(bytes, point); }) .OnSend((server, point, bytes) => {
Console.WriteLine($"服務端發(fā)送數(shù)據(jù):目標[{point.ToString()}]數(shù)據(jù):{Encoding.UTF8.GetString(bytes)}");
}) .OnStarted(server => { Console.WriteLine($"服務端啟動"); }).BuildAsync();
Console.ReadLine(); } } }
* 客戶端 using Coldairarrow.DotNettySocket; using System; using System.Net;
using System.Text; using System.Threading.Tasks; namespace UdpSocket.Client {
class Program { static async Task Main(string[] args) { var theClient = await
SocketBuilderFactory.GetUdpSocketBuilder() .OnClose(server => {
Console.WriteLine($"客戶端關閉"); }) .OnException(ex => {
Console.WriteLine($"客戶端異常:{ex.Message}"); }) .OnRecieve((server, point, bytes)
=> {
Console.WriteLine($"客戶端:收到來自[{point.ToString()}]數(shù)據(jù):{Encoding.UTF8.GetString(bytes)}");
}) .OnSend((server, point, bytes) => {
Console.WriteLine($"客戶端發(fā)送數(shù)據(jù):目標[{point.ToString()}]數(shù)據(jù):{Encoding.UTF8.GetString(bytes)}");
}) .OnStarted(server => { Console.WriteLine($"客戶端啟動"); }).BuildAsync(); while
(true) { await theClient.Send(Guid.NewGuid().ToString(), new
IPEndPoint(IPAddress.Parse("127.0.0.1"), 6003)); await Task.Delay(1000); } } } }
結尾
以上所有示例在源碼中都有,若覺得不錯請點贊加星星,希望能夠幫助到大家。
有任何問題請及時反饋或加群交流
QQ群1:(已滿)
QQ群2:579202910
熱門工具 換一換