.net4.5中实现了对websocket的支持
在这里我使用的是.net4.0。因此需要对原本的socket发送的数据根据websocket的协议进行解析和打包。
文章参考 http://www.cnblogs.com/dolphinX/p/3462898.html
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace WebSocketServer
{
class Program
{
static void Main(string [] args)
{
WebSocket socket = new WebSocket();
socket.start(8064 );
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace WebSocketServer
{
public class Session
{
private Socket _sockeclient;
private byte [] _buffer;
private string _ip;
private bool _isweb = false ;
public Socket SockeClient
{
set { _sockeclient = value ; }
get { return _sockeclient; }
}
public byte [] buffer
{
set { _buffer = value ; }
get { return _buffer; }
}
public string IP
{
set { _ip = value ; }
get { return _ip; }
}
public bool isWeb
{
set { _isweb = value ; }
get { return _isweb; }
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
namespace WebSocketServer
{
public class WebSocket
{
private Dictionary<string , Session> SessionPool = new Dictionary<string , Session>();
private Dictionary<string , string > MsgPool = new Dictionary<string , string >();
#region 启动WebSocket服务
public void start (int port)
{
Socket SockeServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
SockeServer.Bind(new IPEndPoint(IPAddress.Any, port));
SockeServer.Listen(20 );
SockeServer.BeginAccept(new AsyncCallback(Accept), SockeServer);
Console.WriteLine("服务已启动" );
Console.WriteLine("按任意键关闭服务" );
Console.ReadLine();
}
#endregion
#region 处理客户端连接请求
private void Accept (IAsyncResult socket)
{
Socket SockeServer = (Socket)socket.AsyncState;
Socket SockeClient = SockeServer.EndAccept(socket);
byte [] buffer = new byte [4096 ];
try
{
SockeClient.BeginReceive(buffer, 0 , buffer.Length, SocketFlags.None, new AsyncCallback(Recieve), SockeClient);
Session session = new Session();
session.SockeClient = SockeClient;
session.IP = SockeClient.RemoteEndPoint.ToString();
session.buffer = buffer;
lock (SessionPool)
{
if (SessionPool.ContainsKey(session.IP))
{
this .SessionPool.Remove(session.IP);
}
this .SessionPool.Add(session.IP, session);
}
SockeServer.BeginAccept(new AsyncCallback(Accept), SockeServer);
Console.WriteLine(string .Format("Client {0} connected" , SockeClient.RemoteEndPoint));
}
catch (Exception ex)
{
Console.WriteLine("Error : " + ex.ToString());
}
}
#endregion
#region 处理接收的数据
private void Recieve (IAsyncResult socket)
{
Socket SockeClient = (Socket)socket.AsyncState;
string IP = SockeClient.RemoteEndPoint.ToString();
if (SockeClient == null || !SessionPool.ContainsKey(IP))
{
return ;
}
try
{
int length = SockeClient.EndReceive(socket);
byte [] buffer = SessionPool[IP].buffer;
SockeClient.BeginReceive(buffer, 0 , buffer.Length, SocketFlags.None, new AsyncCallback(Recieve), SockeClient);
string msg = Encoding.UTF8.GetString(buffer, 0 , length);
if (msg.Contains("Sec-WebSocket-Key" ))
{
SockeClient.Send(PackageHandShakeData(buffer, length));
SessionPool[IP].isWeb = true ;
return ;
}
if (SessionPool[IP].isWeb)
{
msg = AnalyzeClientData(buffer, length);
}
byte [] msgBuffer = PackageServerData(msg);
foreach (Session se in SessionPool.Values)
{
se.SockeClient.Send(msgBuffer, msgBuffer.Length, SocketFlags.None);
}
}
catch
{
SockeClient.Disconnect(true );
Console.WriteLine("客户端 {0} 断开连接" , IP);
SessionPool.Remove(IP);
}
}
#endregion
#region 客户端和服务端的响应
#endregion
#region 打包请求连接数据
private byte [] PackageHandShakeData (byte [] handShakeBytes, int length)
{
string handShakeText = Encoding.UTF8.GetString(handShakeBytes, 0 , length);
string key = string .Empty;
Regex reg = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n" );
Match m = reg.Match(handShakeText);
if (m.Value != "" )
{
key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n" , "$1" ).Trim();
}
byte [] secKeyBytes = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ));
string secKey = Convert.ToBase64String(secKeyBytes);
var responseBuilder = new StringBuilder();
responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + "\r\n" );
responseBuilder.Append("Upgrade: websocket" + "\r\n" );
responseBuilder.Append("Connection: Upgrade" + "\r\n" );
responseBuilder.Append("Sec-WebSocket-Accept: " + secKey + "\r\n\r\n" );
return Encoding.UTF8.GetBytes(responseBuilder.ToString());
}
#endregion
#region 处理接收的数据
private string AnalyzeClientData (byte [] recBytes, int length)
{
int start = 0 ;
if (length < 2 ) return "" ;
bool IsEof = (recBytes[start] >> 7 ) > 0 ;
if (!IsEof) return "" ;
start++;
bool hasMask = (recBytes[start] >> 7 ) > 0 ;
if (!hasMask) return "" ;
UInt64 mPackageLength = (UInt64)recBytes[start] & 0x7F ;
start++;
byte [] Masking_key = new byte [4 ];
byte [] mDataPackage;
if (mPackageLength == 126 )
{
mPackageLength = (UInt64)(recBytes[start] << 8 | recBytes[start + 1 ]);
start += 2 ;
}
if (mPackageLength == 127 )
{
mPackageLength = (UInt64)(recBytes[start] << (8 * 7 ) | recBytes[start] << (8 * 6 ) | recBytes[start] << (8 * 5 ) | recBytes[start] << (8 * 4 ) | recBytes[start] << (8 * 3 ) | recBytes[start] << (8 * 2 ) | recBytes[start] << 8 | recBytes[start + 1 ]);
start += 8 ;
}
mDataPackage = new byte [mPackageLength];
for (UInt64 i = 0 ; i < mPackageLength; i++)
{
mDataPackage[i] = recBytes[i + (UInt64)start + 4 ];
}
Buffer.BlockCopy(recBytes, start, Masking_key, 0 , 4 );
for (UInt64 i = 0 ; i < mPackageLength; i++)
{
mDataPackage[i] = (byte )(mDataPackage[i] ^ Masking_key[i % 4 ]);
}
return Encoding.UTF8.GetString(mDataPackage);
}
#endregion
#region 发送数据
private byte [] PackageServerData (string msg)
{
byte [] content = null ;
byte [] temp = Encoding.UTF8.GetBytes(msg);
if (temp.Length < 126 )
{
content = new byte [temp.Length + 2 ];
content[0 ] = 0x81 ;
content[1 ] = (byte )temp.Length;
Buffer.BlockCopy(temp, 0 , content, 2 , temp.Length);
}
else if (temp.Length < 0xFFFF )
{
content = new byte [temp.Length + 4 ];
content[0 ] = 0x81 ;
content[1 ] = 126 ;
content[2 ] = (byte )(temp.Length & 0xFF );
content[3 ] = (byte )(temp.Length >> 8 & 0xFF );
Buffer.BlockCopy(temp, 0 , content, 4 , temp.Length);
}
return content;
}
#endregion
}
}