




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第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請(qǐng)求轉(zhuǎn)換3響應(yīng)轉(zhuǎn)換
classServerHelper
{
///summary
///輸出連接頭信息
////summary
publicstaticstringResponseHeader(stringrequestHeader)
{
Hashtabletable=newHashtable();
//拆分成鍵值對(duì),保存到哈希表
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
///解碼請(qǐng)求內(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("暫不處理超長(zhǎng)內(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ù)器斷開(kāi)",address);
ClientManager.Close(address);
Console.WriteLine(address+"已從服務(wù)器斷開(kāi)");
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)聽(tīng)請(qǐng)求
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)聽(tīng)
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);//開(kāi)始監(jiān)聽(tīng)
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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年企業(yè)管理師考試試題及答案拓展
- 2025年統(tǒng)計(jì)師職業(yè)資格考試試卷及答案
- 2025年數(shù)字營(yíng)銷(xiāo)師考試試題及答案
- 2025年護(hù)理管理與實(shí)踐考試試題及答案
- 2025年創(chuàng)意寫(xiě)作與文學(xué)分析考試卷及答案
- 知識(shí)產(chǎn)權(quán)收益分割與科技成果轉(zhuǎn)化合作協(xié)議
- 金融機(jī)構(gòu)間貨幣結(jié)算服務(wù)協(xié)議補(bǔ)充
- 離職人員保密協(xié)議與競(jìng)業(yè)限制合同(體育用品行業(yè))
- 購(gòu)物中心珠寶區(qū)品牌租賃與區(qū)域市場(chǎng)合作合同
- 城市級(jí)停車(chē)誘導(dǎo)系統(tǒng)與城市供電合同
- 應(yīng)急廣播終端安裝施工規(guī)范
- 以“蛋白質(zhì)”為主線的單元境脈設(shè)計(jì)與教學(xué)重構(gòu)
- 墻面木飾面施工方案
- 案例3 哪吒-全球首個(gè)“??找惑w”跨域航行器平臺(tái)
- 奇恒之腑課件
- 醫(yī)院保密培訓(xùn)課件
- 《無(wú)人機(jī)航拍技術(shù)》項(xiàng)目1任務(wù)2 無(wú)人機(jī)航拍應(yīng)用
- 糖尿病視網(wǎng)膜病變專(zhuān)家共識(shí)
- 管理會(huì)計(jì)學(xué)(第6版) 課件 郭曉梅 第6、7章 短期經(jīng)營(yíng)方案的分析評(píng)價(jià);長(zhǎng)期投資方案的經(jīng)濟(jì)評(píng)價(jià)
- 2023年上海鐵路局集團(tuán)有限公司招聘筆試真題
- DB11T 1608-2018 預(yù)拌盾構(gòu)注漿料應(yīng)用技術(shù)規(guī)程
評(píng)論
0/150
提交評(píng)論