C# Websocket連接實(shí)現(xiàn)wss協(xié)議
一、什么是Websocket?
1.WebSocket是HTML5下一種新的協(xié)議(websocket協(xié)議本質(zhì)上是一個(gè)基于tcp的協(xié)議)
2.它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工通信,能更好的節(jié)省服務(wù)器資源和帶寬并達(dá)到實(shí)時(shí)通訊的目的
3.Websocket是一個(gè)持久化的協(xié)議
二、Websocket、Socket、Http、Mqtt之間的區(qū)別?
Socket:
Socket是對(duì)tcp/ip協(xié)議族的封裝的接口,Socket連接可以指定不同的傳輸層協(xié)議,即TCP或UDP,由于它是基于tcp/ip的,所以一般用在局域網(wǎng)內(nèi)通信。
WebSocket:
WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議,和http協(xié)議一樣屬于應(yīng)用層協(xié)議,是一種讓客戶(hù)端和服務(wù)器之間能進(jìn)行雙向?qū)崟r(shí)通信(全雙工)的技術(shù),且支持長(zhǎng)連接,可以進(jìn)行互聯(lián)網(wǎng)間通信。引入ws和wss分別代表明文和密文的websocket協(xié)議,且默認(rèn)端口使用80或443,幾乎與http一致,WebSocket也要有一個(gè)握手過(guò)程,然后才能正式收發(fā)數(shù)據(jù),由于數(shù)據(jù)包頭部協(xié)議較小,不同于http每次請(qǐng)求需要攜帶完整的頭部,所以網(wǎng)絡(luò)開(kāi)銷(xiāo)比較少,長(zhǎng)連接也讓延遲明顯更少(不需要重復(fù)新建連接)。
MQTT:
MQTT協(xié)議是為大量計(jì)算能力有限,且工作在低帶寬、不可靠的網(wǎng)絡(luò)的遠(yuǎn)程傳感器和控制設(shè)備通訊而設(shè)計(jì)的協(xié)議,它具有以下主要的幾項(xiàng)特性:
1.使用發(fā)布/訂閱消息模式,提供一對(duì)多的消息發(fā)布,解除應(yīng)用程序耦合;
2.對(duì)負(fù)載內(nèi)容屏蔽的消息傳輸;
3.使用 TCP/IP 提供網(wǎng)絡(luò)連接;
HTTP:
HTTP是一個(gè)屬于應(yīng)用層的,基于TCP/IP通信協(xié)議來(lái)傳遞數(shù)據(jù)(HTML 文件, 圖片文件, 查詢(xún)結(jié)果等)。
通信方式:
1.瀏覽器作為HTTP客戶(hù)端通過(guò)URL向HTTP服務(wù)端即WEB服務(wù)器發(fā)送請(qǐng)求。Web服務(wù)器根據(jù)接收到的請(qǐng)求后,向客戶(hù)端發(fā)送響應(yīng)信息。
2.HTTP之請(qǐng)求消息Request:請(qǐng)求行(request line)、請(qǐng)求頭部(header)、空行和請(qǐng)求數(shù)據(jù)四個(gè)部分組成。
3.HTTP之響應(yīng)消息Response:HTTP響應(yīng)也由四個(gè)部分組成,分別是:狀態(tài)行、消息報(bào)頭、空行和響應(yīng)正文。
若connection 模式為close,則服務(wù)器會(huì)主動(dòng)關(guān)閉TCP連接,客戶(hù)端被動(dòng)關(guān)閉連接,釋放TCP連接;若connection 模式為keepalive,則該連接會(huì)保持一段時(shí)間,在該時(shí)間內(nèi)可以繼續(xù)接收請(qǐng)求;
三、WS和WSS協(xié)議
WS協(xié)議和WSS協(xié)議兩個(gè)均是WebSocket協(xié)議的SCHEM,兩者一個(gè)是非安全的,一個(gè)是安全的。也是統(tǒng)一的資源標(biāo)志符。就好比HTTP協(xié)議和HTTPS協(xié)議的差別。非安全的沒(méi)有證書(shū),安全的需要SSL證書(shū)。(SSL是Netscape所研發(fā),用來(lái)保障網(wǎng)絡(luò)中數(shù)據(jù)傳輸?shù)陌踩?,主要是運(yùn)用數(shù)據(jù)加密的技術(shù),能夠避免數(shù)據(jù)在傳輸過(guò)程被不被竊取或者監(jiān)聽(tīng)。)其中WSS表示在TLS之上的WebSocket。WS一般默認(rèn)是80端口,而WSS默認(rèn)是443端口,大多數(shù)網(wǎng)站用的就是80和433端口。(在高防防護(hù)過(guò)程中,80和433端口的網(wǎng)站是需要備案才可以接入國(guó)內(nèi)的。)當(dāng)然網(wǎng)站也會(huì)有別的端口,這種如果做高防是方案是可以用海外高防的。WS和WSS的體現(xiàn)形式分別是TCP+WS AS WS ,TCP+TLS+WS AS WS。服務(wù)器網(wǎng)址就是 URL。最后墨者安全再說(shuō)下WebSocket協(xié)議的特點(diǎn):建立在 TCP 協(xié)議之上,服務(wù)端實(shí)現(xiàn)容易;與 HTTP 協(xié)議有良好的兼容性,握手時(shí)不容易被屏蔽,可以通過(guò)各種 HTTP 代理服務(wù)器;數(shù)據(jù)輕量,實(shí)時(shí)通訊;可以發(fā)送文本和二進(jìn)制數(shù)據(jù)。不限制同源,客戶(hù)端可以與任意服務(wù)器端進(jìn)行通訊。因此WebSocket協(xié)議的出現(xiàn),為很多人解決了關(guān)于擴(kuò)展以及兼容性協(xié)議的煩惱問(wèn)題。
WSS連接:由于wss是基于SSL,所以需要進(jìn)行雙向驗(yàn)證,客戶(hù)端連接服務(wù)端時(shí),我需要添加證書(shū)(服務(wù)端不驗(yàn)證可以不添加),服務(wù)端進(jìn)行驗(yàn)證。注意:客戶(hù)也需要對(duì)服務(wù)端進(jìn)行驗(yàn)證,所以需要添加服務(wù)端證書(shū)回調(diào),進(jìn)行驗(yàn)證,這是很多人忽視,所以出現(xiàn)無(wú)法連接遠(yuǎn)程服務(wù)器,TLS/SSL驗(yàn)證失敗的提示。
public MainWindow()
{
InitializeComponent();
RemoteCertificateValidationCallback remote = ValidateServerCertificate;
ServicePointManager.ServerCertificateValidationCallback = remote;
}
/// <summary>
/// 服務(wù)端驗(yàn)證
/// </summary>
/// <param name="sender"></param>
/// <param name="certificate"></param>
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns></returns>
public bool ValidateServerCertificate( object sender,X509Certificate certificate,X509Chain chain,SslPolicyErrors sslPolicyErrors)
{
return true ;
}
/// <summary>
/// WebSocket客戶(hù)端連接
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
public async Task Connect()
{
CancellationTokenSource t = new CancellationTokenSource();
try
{
client.Options.SetRequestHeader("key", "value");
X509Certificate2 cert = new X509Certificate2("xxx.cert");
client.Options.ClientCertificates.Add(cert);
Uri uri = new Uri("wss://xxxxxx");
//var config=new ServerConfig
await client.ConnectAsync(uri, t.Token);
Thread.Sleep(300);
Console.WriteLine($"鏈接websocket:[{uri}] 完成");
Task s1 = new Task(Receive, t, t.Token, TaskCreationOptions.LongRunning);
s1.Start();
token = t;
Console.WriteLine("Send Hello");
}
catch (Exception ex)
{
Console.WriteLine($"鏈接websocket:[{uri}] 失敗", ex.Message);
}
}
/// <summary>
/// Websocket接收
/// </summary>
/// <param name="obj"></param>
private void Receive(object obj)
{
CancellationTokenSource ts = obj as CancellationTokenSource;
byte[] bs = new byte[1024];
while (!ts.Token.IsCancellationRequested)
{
try
{
ArraySegment<byte> buff = new ArraySegment<byte>(bs, 0, bs.Length);
Task<WebSocketReceiveResult> res = client.ReceiveAsync(buff, ts.Token);
res.Wait();
if (ts.Token.IsCancellationRequested)
{
return;
}
if (WebSocketCloseStatus.NormalClosure == res.Result.CloseStatus)
{
Console.WriteLine($"websocket:與服務(wù)器斷開(kāi)鏈接:{res.Result.CloseStatus} --> Desc :{res.Result.CloseStatusDescription}");
ts.Cancel();
return;
}
string strData = encod.GetString(bs, 0, res.Result.Count);
Console.WriteLine(strData);
WsMsg msg = WsMsg.Deserialize(strData);
}
catch (Exception ex)
{
Console.WriteLine("解析或執(zhí)行 websocket:命令失敗", ex);
}
}
}
Websocket客戶(hù)端與服務(wù)端通信代碼參考文章:
WebSocket協(xié)議:5分鐘從入門(mén)到精通 - 程序猿小卡 https://www.cnblogs.com/chyingp/p/websocket-deep-in.html
C# WebSocket_熊思雨的博客 https://blog.csdn.net/qq_38693757/article/details/114933642
C# WebSocket - 南國(guó)葉子 https://www.cnblogs.com/nanguoyezi/p/9351555.html
到此這篇關(guān)于C# Websocket連接實(shí)現(xiàn)wss協(xié)議的文章就介紹到這了,更多相關(guān)C# Websocket連接wss內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
c#關(guān)于JWT跨域身份驗(yàn)證的實(shí)現(xiàn)代碼
這篇文章主要介紹了c#關(guān)于JWT跨域身份驗(yàn)證的實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
RegexOptions.IgnoreCase正則表達(dá)式替換,忽略大小寫(xiě)
RegexOptions.IgnoreCase正則表達(dá)式替換,忽略大小寫(xiě),需要的朋友可以參考一下2013-03-03
C#將Excel中的數(shù)據(jù)轉(zhuǎn)換成DataSet
這篇文章主要介紹了C#將Excel中的數(shù)據(jù)轉(zhuǎn)換成DataSet的方法,非常簡(jiǎn)單實(shí)用,從本人項(xiàng)目中提取出來(lái)的,推薦給大家,希望對(duì)大家學(xué)習(xí)C#能夠有所幫助。2015-03-03
Unity通過(guò)腳本創(chuàng)建網(wǎng)格Mesh的方法
Unity中的網(wǎng)格作為組件不能脫離物體單獨(dú)存在,通過(guò)新建腳本來(lái)實(shí)現(xiàn)相關(guān)操作,本文重點(diǎn)給大家介紹Unity通過(guò)腳本創(chuàng)建網(wǎng)格Mesh的方法,感興趣的朋友一起看看吧2022-04-04
winform實(shí)現(xiàn)拖動(dòng)文件到窗體上的方法
這篇文章主要介紹了winform實(shí)現(xiàn)拖動(dòng)文件到窗體上的方法,以實(shí)例分析了C#中WinForm操作窗體及文件的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-09-09

