




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第C#基于WebSocket實(shí)現(xiàn)聊天室功能本文實(shí)例為大家分享了C#基于WebSocket實(shí)現(xiàn)聊天室功能的具體代碼,供大家參考,具體內(nèi)容如下
前面兩篇溫習(xí)了,C#Socket內(nèi)容
本章根據(jù)Socket異步聊天室修改成WebSocket聊天室
WebSocket特別的地方是握手和消息內(nèi)容的編碼、解碼(添加了ServerHelper協(xié)助處理)
ServerHelper:
usingSystem;
usingSystem.Collections;
usingSystem.Text;
usingSystem.Security.Cryptography;
namespaceSocketDemo
//Server助手負(fù)責(zé):1握手2請求轉(zhuǎn)換3響應(yīng)轉(zhuǎn)換
classServerHelper
{
///summary
///輸出連接頭信息
////summary
publicstaticstringResponseHeader(stringrequestHeader)
{
Hashtabletable=newHashtable();
//拆分成鍵值對,保存到哈希表
string[]rows=requestHeader.Split(newstring[]{"\r\n"},StringSplitOptions.RemoveEmptyEntries);
foreach(stringrowinrows)
{
intsplitIndex=row.IndexOf(':');
if(splitIndex0)
{
table.Add(row.Substring(0,splitIndex).Trim(),row.Substring(splitIndex+1).Trim());
}
}
StringBuilderheader=newStringBuilder();
header.Append("HTTP/1.1101WebSocketProtocolHandshake\r\n");
header.AppendFormat("Upgrade:{0}\r\n",table.ContainsKey("Upgrade")table["Upgrade"].ToString():string.Empty);
header.AppendFormat("Connection:{0}\r\n",table.ContainsKey("Connection")table["Connection"].ToString():string.Empty);
header.AppendFormat("WebSocket-Origin:{0}\r\n",table.ContainsKey("Sec-WebSocket-Origin")table["Sec-WebSocket-Origin"].ToString():string.Empty);
header.AppendFormat("WebSocket-Location:{0}\r\n",table.ContainsKey("Host")table["Host"].ToString():string.Empty);
stringkey=table.ContainsKey("Sec-WebSocket-Key")table["Sec-WebSocket-Key"].ToString():string.Empty;
stringmagic="258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
header.AppendFormat("Sec-WebSocket-Accept:{0}\r\n",Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key+magic))));
header.Append("\r\n");
returnheader.ToString();
}
///summary
///解碼請求內(nèi)容
////summary
publicstaticstringDecodeMsg(Byte[]buffer,intlen)
{
if(buffer[0]!=0x81
||(buffer[0]0x80)!=0x80
||(buffer[1]0x80)!=0x80)
{
returnnull;
}
Byte[]mask=newByte[4];
intbeginIndex=0;
intpayload_len=buffer[1]0x7F;
if(payload_len==0x7E)
{
Array.Copy(buffer,4,mask,0,4);
payload_len=payload_len0x00000000;
payload_len=payload_len|buffer[2];
payload_len=(payload_len8)|buffer[3];
beginIndex=8;
}
elseif(payload_len!=0x7F)
{
Array.Copy(buffer,2,mask,0,4);
beginIndex=6;
}
for(inti=0;ipayload_len;i++)
{
buffer[i+beginIndex]=(byte)(buffer[i+beginIndex]^mask[i%4]);
}
returnEncoding.UTF8.GetString(buffer,beginIndex,payload_len);
}
///summary
///編碼響應(yīng)內(nèi)容
////summary
publicstaticbyte[]EncodeMsg(stringcontent)
{
byte[]bts=null;
byte[]temp=Encoding.UTF8.GetBytes(content);
if(temp.Length126)
{
bts=newbyte[temp.Length+2];
bts[0]=0x81;
bts[1]=(byte)temp.Length;
Array.Copy(temp,0,bts,2,temp.Length);
}
elseif(temp.Length0xFFFF)
{
bts=newbyte[temp.Length+4];
bts[0]=0x81;
bts[1]=126;
bts[2]=(byte)(temp.Length0xFF);
bts[3]=(byte)(temp.Length80xFF);
Array.Copy(temp,0,bts,4,temp.Length);
}
else
{
byte[]st=System.Text.Encoding.UTF8.GetBytes(string.Format("暫不處理超長內(nèi)容").ToCharArray());
}
returnbts;
}
}
}
Server:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Net;
usingSystem.Net.Sockets;
namespaceSocketDemo
classClientInfo
{
publicSocketSocket{get;set;}
publicboolIsOpen{get;set;}
publicstringAddress{get;set;}
}
//管理Client
classClientManager
{
staticListClientInfoclientList=newListClientInfo
publicstaticvoidAdd(ClientInfoinfo)
{
if(!IsExist(info.Address))
{
clientList.Add(info);
}
}
publicstaticboolIsExist(stringaddress)
{
returnclientList.Exists(item=string.Compare(address,item.Address,true)==0);
}
publicstaticboolIsExist(stringaddress,boolisOpen)
{
returnclientList.Exists(item=string.Compare(address,item.Address,true)==0item.IsOpen==isOpen);
}
publicstaticvoidOpen(stringaddress)
{
clientList.ForEach(item=
{
if(string.Compare(address,item.Address,true)==0)
{
item.IsOpen=true;
}
});
}
publicstaticvoidClose(stringaddress=null)
{
clientList.ForEach(item=
{
if(address==null||string.Compare(address,item.Address,true)==0)
{
item.IsOpen=false;
item.Socket.Shutdown(SocketShutdown.Both);
}
});
}
//發(fā)送消息到ClientList
publicstaticvoidSendMsgToClientList(stringmsg,stringaddress=null)
{
clientList.ForEach(item=
{
if(item.IsOpen(address==null||item.Address!=address))
{
SendMsgToClient(item.Socket,msg);
}
});
}
publicstaticvoidSendMsgToClient(Socketclient,stringmsg)
{
byte[]bt=ServerHelper.EncodeMsg(msg);
client.BeginSend(bt,0,bt.Length,SocketFlags.None,newAsyncCallback(SendTarget),client);
}
privatestaticvoidSendTarget(IAsyncResultres)
{
//Socketclient=(Socket)res.AsyncState;
//intsize=client.EndSend(res);
}
}
//接收消息
classReceiveHelper
{
publicbyte[]Bytes{get;set;}
publicvoidReceiveTarget(IAsyncResultres)
{
Socketclient=(Socket)res.AsyncState;
intsize=client.EndReceive(res);
if(size0)
{
stringaddress=client.RemoteEndPoint.ToString();//獲取Client的IP和端口
stringstringdata=null;
if(ClientManager.IsExist(address,false))//握手
{
stringdata=Encoding.UTF8.GetString(Bytes,0,size);
ClientManager.SendMsgToClient(client,ServerHelper.ResponseHeader(stringdata));
ClientManager.Open(address);
}
else
{
stringdata=ServerHelper.DecodeMsg(Bytes,size);
}
if(stringdata.IndexOf("exit")-1)
{
ClientManager.SendMsgToClientList(address+"已從服務(wù)器斷開",address);
ClientManager.Close(address);
Console.WriteLine(address+"已從服務(wù)器斷開");
Console.WriteLine(address+""+DateTimeOffset.Now.ToString("G"));
return;
}
else
{
Console.WriteLine(stringdata);
Console.WriteLine(address+""+DateTimeOffset.Now.ToString("G"));
ClientManager.SendMsgToClientList(stringdata,address);
}
}
//繼續(xù)等待
client.BeginReceive(Bytes,0,Bytes.Length,SocketFlags.None,newAsyncCallback(ReceiveTarget),client);
}
}
//監(jiān)聽請求
classAcceptHelper
{
publicbyte[]Bytes{get;set;}
publicvoidAcceptTarget(IAsyncResultres)
{
Socketserver=(Socket)res.AsyncState;
Socketclient=server.EndAccept(res);
stringaddress=client.RemoteEndPoint.ToString();
ClientManager.Add(newClientInfo(){Socket=client,Address=address,IsOpen=false});
ReceiveHelperrs=newReceiveHelper(){Bytes=this.Bytes};
IAsyncResultrecres=client.BeginReceive(rs.Bytes,0,rs.Bytes.Length,SocketFlags.None,newAsyncCallback(rs.ReceiveTarget),client);
//繼續(xù)監(jiān)聽
server.BeginAccept(newAsyncCallback(AcceptTarget),server);
}
}
classProgram
{
staticvoidMain(string[]args)
{
Socketserver=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
server.Bind(newIPEndPoint(IPAddress.Parse(""),200));//綁定IP+端口
server.Listen(10);//開始監(jiān)聽
Console.WriteLine("等待連接...");
AcceptHelperca=newAcceptHelper(){Bytes=newbyte[2048]};
IAsyncResultres=server.BeginAccept(newAsyncCallback(ca.AcceptTarget),server);
stringstr=string.Empty;
while(str!="exit")
{
str=Console.ReadLine();
Console.WriteLine("ME:"+DateTimeOffset.Now.ToString("G"));
ClientManager.SendMsgToClientList(str);
}
ClientManager.Close();
server.Close();
}
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 中級經(jīng)濟(jì)師考試經(jīng)歷分享試題及答案
- 水利水電工程后評估試題及答案
- 工程項(xiàng)目管理核心技術(shù)試題及答案
- 風(fēng)險(xiǎn)評估與應(yīng)對試題及答案
- 2025年管理人員安全培訓(xùn)考試試題附參考答案(預(yù)熱題)
- 2025年廠級員工安全培訓(xùn)考試試題答案完美
- 2024-2025公司三級安全培訓(xùn)考試試題附完整答案(典優(yōu))
- 2025-2030年集群通信系統(tǒng)設(shè)備產(chǎn)業(yè)市場發(fā)展分析及前景趨勢與投資管理研究報(bào)告
- 2025-2030年鋁錳合金行業(yè)市場深度調(diào)研及前景趨勢與投資研究報(bào)告
- 2025-2030年鋼板材行業(yè)市場現(xiàn)狀供需分析及投資評估規(guī)劃分析研究報(bào)告
- 游艇概論-第6章-游艇的動力裝置
- G520-1~2(2020年合訂本)鋼吊車梁(6m~9m)(2020年合訂本)
- 2024年度中國鈉離子電池報(bào)告
- 川崎病病例討論
- 航空服務(wù)禮儀與溝通考核試卷
- 中外運(yùn)社招在線測評題
- 《有機(jī)化學(xué):糖》課件
- 【專項(xiàng)訓(xùn)練】相似三角形五大模型+訓(xùn)練(共45題)(原卷版+解析)
- 智慧果園系統(tǒng)構(gòu)建與應(yīng)用
- 11《杠桿》教學(xué)設(shè)計(jì)-2023-2024學(xué)年科學(xué)五年級下冊人教鄂教版
- TJSHLW 001-2024 土壤修復(fù)管控工程全過程監(jiān)管數(shù)據(jù)接入規(guī)范
評論
0/150
提交評論