WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
当你获取 Web Socket 连接后,你可以通过 send() 方法来向服务器发送数据,并通过 onmessage 事件来接收服务器返回的数据。
其实WebSocket与Socket区别不大,只是客户端是在浏览器上实现的,替代了传统的轮询机制,减少带宽和资源
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebSocketsServer
{
///
/// 声明新连接处理事件
///
///
///
public delegate void NewConnection_EventHandler(string loginName, EventArgs args);
///
/// 声明接收数据处理事件
///
///
///
///
public delegate void DataReceive_EventHandler(object sender, string message, EventArgs args);
///
/// 声明断开连接处理事件
///
///
///
public delegate void Disconncetion_EventHandler(object sender, string message, EventArgs args);
}
WebSocketServer代码
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace WebSocketsServer
{
///
/// Socket服务端
///
public class WebSocketServer : IDisposable
{
#region 私有变量
///
/// ip
///
private string _ip = string.Empty;
///
/// 端口
///
private int _port = 0;
///
/// 服务器地址
///
private string _serverLocation = string.Empty;
///
/// Socket对象
///
private Socket _socket = null;
///
/// 监听的最大连接数
///
private int maxListenConnect = 10;
///
/// 是否关闭Socket对象
///
private bool isDisposed = false;
private Logger logger = null;
///
/// buffer缓存区字节数
///
private int maxBufferSize = 0;
///
/// 第一个字节,以0x00开始
///
private byte[] FirstByte;
///
/// 最后一个字节,以0xFF结束
///
private byte[] LastByte;
#endregion
#region 声明Socket处理事件
///
/// Socket新连接事件
///
public event NewConnection_EventHandler NewConnectionHandler;
///
/// Socket接收消息事件
///
public event DataReceive_EventHandler DataReceiveHandler;
///
/// Socket断开连接事件
///
public event Disconncetion_EventHandler DisconnectionHandler;
#endregion
///
/// 存放SocketConnection集合
///
List SocketConnections = new List();
#region 构造函数
public WebSocketServer()
{
this._ip = GetLocalMachineIPAddress().ToString();
this._port = 9000;
this._serverLocation = string.Format("ws://{0}:{1}", this._ip, this._port);
Initialize();
}
public WebSocketServer(string ip, int port)
{
this._ip = ip;
this._port = port;
this._serverLocation = string.Format("ws://{0}:{1}", this._ip, this._port);
Initialize();
}
public WebSocketServer(string ip, int port, string serverLocation)
{
this._ip = ip;
this._port = port;
this._serverLocation = serverLocation;
Initialize();
}
#endregion
///
/// 初始化私有变量
///
private void Initialize()
{
isDisposed = false;
logger = new Logger()
{
LogEvents = true
};
maxBufferSize = 1024 * 1024;
maxListenConnect = 500;
FirstByte = new byte[maxBufferSize];
LastByte = new byte[maxBufferSize];
FirstByte[0] = 0x00;
LastByte[0] = 0xFF;
}
///
/// 开启服务
///
public void StartServer()
{
try
{
//实例化套接字
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建IP对象
IPAddress address = GetLocalMachineIPAddress();
//创建网络端点,包括ip和port
IPEndPoint endPoint = new IPEndPoint(address, _port);
//将socket与本地端点绑定
_socket.Bind(endPoint);
//设置最大监听数
_socket.Listen(maxListenConnect);
logger.Log(string.Format("聊天服务器启动。监听地址:{0}, 端口:{1}", this._ip, this._port));
logger.Log(string.Format("WebSocket服务器地址: ws://{0}:{1}", this._ip, this._port));
//开始监听客户端
Thread thread = new Thread(ListenClientConnect);
thread.Start();
}
catch (Exception ex)
{
logger.Log(ex.Message);
}
}
///
/// 监听客户端连接
///
private void ListenClientConnect()
{
try
{
while (true)
{
//为新建连接创建的Socket
Socket socket = _socket.Accept();
if (socket != null)
{
//线程不休眠的话,会导致回调函数的AsyncState状态出异常
Thread.Sleep(100);
SocketConnection socketConnection = new SocketConnection(this._ip, this._port, this._serverLocation)
{
ConnectionSocket = socket
};
//绑定事件
socketConnection.NewConnectionHandler += SocketConnection_NewConnectionHandler;
socketConnection.DataReceiveHandler += SocketConnection_DataReceiveHandler;
socketConnection.DisconnectionHandler += SocketConnection_DisconnectionHandler;
//从开始连接的Socket中异步接收消息
socketConnection.ConnectionSocket.BeginReceive(socketConnection.receivedDataBuffer,
0, socketConnection.receivedDataBuffer.Length,
0, new AsyncCallback(socketConnection.ManageHandshake),
socketConnection.ConnectionSocket.Available);
//存入集合,以便在Socket发送消息时发送给所有连接的Socket套接字
SocketConnections.Add(socketConnection);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
///
/// SocketConnection监听的新连接事件
///
///
///
private void SocketConnection_NewConnectionHandler(string loginName, EventArgs args)
{
NewConnectionHandler?.Invoke(loginName, EventArgs.Empty);
}
///
/// SocketConnection监听的消息接收事件
///
///
///
///
private void SocketConnection_DataReceiveHandler(object sender, string msgData, EventArgs args)
{
//新用户连接进来时显示欢迎信息
//SocketConnection socketConnection = sender as SocketConnection;
Send(msgData);
}
///
/// SocketConnection监听的断开连接事件
///
///
///
private void SocketConnection_DisconnectionHandler(object sender, string message, EventArgs args)
{
if (sender is SocketConnection socket)
{
Send(message);
socket.ConnectionSocket.Close();
SocketConnections.Remove(socket);
}
}
///
/// 发送消息
///
///
public void Send(string message)
{
//给所有连接上的发送消息
foreach (SocketConnection socket in SocketConnections)
{
if (!socket.ConnectionSocket.Connected)
{
continue;
}
try
{
if (socket.IsDataMasked)
{
DataFrame dataFrame = new DataFrame(message);
socket.ConnectionSocket.Send(dataFrame.GetBytes());
}
else
{
socket.ConnectionSocket.Send(FirstByte);
socket.ConnectionSocket.Send(Encoding.UTF8.GetBytes(message));
socket.ConnectionSocket.Send(LastByte);
}
}
catch (Exception ex)
{
logger.Log(ex.Message);
}
}
}
///
/// 获取当前主机的IP地址
///
///
private IPAddress GetLocalMachineIPAddress()
{
//获取计算机主机名
string hostName = Dns.GetHostName();
//将主机名解析为IPHostEntry
IPHostEntry hostEntry = Dns.GetHostEntry(hostName);
foreach (IPAddress address in hostEntry.AddressList)
{
//IP4寻址协议
if (address.AddressFamily == AddressFamily.InterNetwork)
{
return address;
}
}
return hostEntry.AddressList[0];
}
~WebSocketServer()
{
Close();
}
public void Dispose()
{
Close();
}
public void Close()
{
if (!isDisposed)
{
isDisposed = true;
if (_socket != null)
{
_socket.Close();
}
foreach (SocketConnection socketConnection in SocketConnections)
{
socketConnection.ConnectionSocket.Close();
}
SocketConnections.Clear();
GC.SuppressFinalize(this);
}
}
}
}
自定义的SocketConnection类
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace WebSocketsServer
{
///
/// Socket成功建立的连接
///
public class SocketConnection
{
///
/// 新的Socket连接
///
public Socket ConnectionSocket = null;
#region Socket监听事件
///
/// 新连接事件
///
public event NewConnection_EventHandler NewConnectionHandler;
///
/// 数据接收事件
///
public event DataReceive_EventHandler DataReceiveHandler;
///
/// 断开连接事件
///
public event Disconncetion_EventHandler DisconnectionHandler;
#endregion
#region 私有变量
private string _ip = string.Empty;
private int _port = 0;
private string _serverLocation = string.Empty;
private Logger logger;
private string loginId;
public string LoginId
{
get => loginId; set => loginId = value;
}
private bool isDataMasked;
public bool IsDataMasked { get => isDataMasked; set => isDataMasked = value; }
///
/// 最大缓存区字节数
///
private int maxBufferSize = 0;
///
/// 握手协议信息
///
private string handshake = string.Empty;
///
/// 握手协议信息(new)
///
private string newHandshake = string.Empty;
///
/// 接收消息的数据缓存区
///
public byte[] receivedDataBuffer;
private byte[] firstByte;
private byte[] lastByte;
private byte[] serverKey1;
private byte[] serverKey2;
#endregion
#region 构造函数
public SocketConnection()
{
Initialize();
}
public SocketConnection(string ip, int port, string serverLocation)
{
this._ip = ip;
this._port = port;
this._serverLocation = serverLocation;
Initialize();
}
#endregion
///
/// 初始化变量
///
private void Initialize()
{
logger = new Logger();
maxBufferSize = 1024 * 1024;
receivedDataBuffer = new byte[maxBufferSize];
firstByte = new byte[maxBufferSize];
lastByte = new byte[maxBufferSize];
firstByte[0] = 0x00;
lastByte[0] = 0xFF;
//webSocket携带头信息
handshake = "HTTP/1.1 101 Web Socket Protocol Handshake" + Environment.NewLine;
handshake += "Upgrade: WebSocket" + Environment.NewLine;
handshake += "Connection: Upgrade" + Environment.NewLine;
handshake += "Sec-WebSocket-Origin: " + "{0}" + Environment.NewLine;
handshake += string.Format("Sec-WebSocket-Location: " + "ws://{0}:{1}" + Environment.NewLine, this._ip, this._port);
handshake += Environment.NewLine;
newHandshake = "HTTP/1.1 101 Switching Protocols" + Environment.NewLine;
newHandshake += "Upgrade: WebSocket" + Environment.NewLine;
newHandshake += "Connection: Upgrade" + Environment.NewLine;
newHandshake += "Sec-WebSocket-Accept: {0}" + Environment.NewLine;
newHandshake += Environment.NewLine;
}
///
/// 处理异步接收消息回调方法
///
///
public void ManageHandshake(IAsyncResult asyncResult)
{
try
{
string header = "Sec-WebSocket-Version:";
int HandshakeLength = (int)asyncResult.AsyncState;
byte[] last8Bytes = new byte[8];
UTF8Encoding encoding = new UTF8Encoding();
String rawClientHandshake = encoding.GetString(receivedDataBuffer, 0, HandshakeLength);
Array.Copy(receivedDataBuffer, HandshakeLength - 8, last8Bytes, 0, 8);
//现在使用的是比较新的WebSocket协议
if (rawClientHandshake.IndexOf(header) != -1)
{
this.isDataMasked = true;
string[] rawClientHandshakeLines = rawClientHandshake.Split(new string[] { Environment.NewLine }, System.StringSplitOptions.RemoveEmptyEntries);
string acceptKey = "";
foreach (string line in rawClientHandshakeLines)
{
if (line.Contains("Sec-WebSocket-Key:"))
{
acceptKey = ComputeWebSocketHandshakeSecurityHash09(line.Substring(line.IndexOf(":") + 2));
}
}
newHandshake = string.Format(newHandshake, acceptKey);
byte[] newHandshakeText = Encoding.UTF8.GetBytes(newHandshake);
//将数据异步发送到连接的socket上
ConnectionSocket.BeginSend(newHandshakeText, 0, newHandshakeText.Length, SocketFlags.None, HandshakeFinished, null);
return;
}
string clientHandshake = encoding.GetString(receivedDataBuffer, 0, receivedDataBuffer.Length - 8);
string[] clientHandshakeLines = clientHandshake.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
logger.Log("新的连接请求来自:" + ConnectionSocket.LocalEndPoint + ".正准备进行连接...");
// Welcome the new client
foreach (string Line in clientHandshakeLines)
{
logger.Log(Line);
if (Line.Contains("Sec-WebSocket-Key1:"))
BuildServerPartialKey(1, Line.Substring(Line.IndexOf(":") + 2));
if (Line.Contains("Sec-WebSocket-Key2:"))
BuildServerPartialKey(2, Line.Substring(Line.IndexOf(":") + 2));
if (Line.Contains("Origin:"))
try
{
handshake = string.Format(handshake, Line.Substring(Line.IndexOf(":") + 2));
}
catch
{
handshake = string.Format(handshake, "null");
}
}
//为客户端建立响应
byte[] handshakeText = Encoding.UTF8.GetBytes(handshake);
byte[] serverHandshakeResponse = new byte[handshakeText.Length + 16];
byte[] serverKey = BuildServerFullKey(last8Bytes);
Array.Copy(handshakeText, serverHandshakeResponse, handshakeText.Length);
Array.Copy(serverKey, 0, serverHandshakeResponse, handshakeText.Length, 16);
logger.Log("发送握手信息 ...");
ConnectionSocket.BeginSend(serverHandshakeResponse, 0, handshakeText.Length + 16, 0, HandshakeFinished, null);
logger.Log(handshake);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
///
/// 由服务端像客户端发送消息完成回调
///
///
private void HandshakeFinished(IAsyncResult asyncResult)
{
//结束挂起的异步发送
ConnectionSocket.EndSend(asyncResult);
ConnectionSocket.BeginReceive(receivedDataBuffer, 0, receivedDataBuffer.Length,
0, new AsyncCallback(Read), null);
NewConnectionHandler?.Invoke("", EventArgs.Empty);
}
private void Read(IAsyncResult asyncResult)
{
if (!ConnectionSocket.Connected)
{
return;
}
string message = string.Empty;
DataFrame dataFrame = new DataFrame(receivedDataBuffer);
try
{
if (!this.isDataMasked)
{
//WebSocket协议:消息以0x00和0xFF作为填充字节发送
UTF8Encoding encoding = new UTF8Encoding();
int startIndex = 0;
int endIndex = 0;
// Search for the start byte
while (receivedDataBuffer[startIndex] == firstByte[0])
{
startIndex++;
}
// Search for the end byte
endIndex = startIndex + 1;
while (receivedDataBuffer[endIndex] != lastByte[0] && endIndex != maxBufferSize - 1)
{
endIndex++;
}
if (endIndex == maxBufferSize - 1)
{
endIndex = maxBufferSize;
}
// Get the message
message = encoding.GetString(receivedDataBuffer, startIndex, endIndex - startIndex);
}//if
else
{
message = dataFrame.Text;
}
if ((message.Length == maxBufferSize && message[0] == Convert.ToChar(65533)) ||
message.Length == 0)
{
//断开连接
logger.Log("message");
if (string.IsNullOrEmpty(message))
{
MessageInfo messageInfo = new MessageInfo()
{
MsgType = MessageType.None,
Message = ""
};
message = JsonConvert.SerializeObject(messageInfo);
}
DisconnectionHandler?.Invoke(this, message, EventArgs.Empty);
}
else
{
if (DataReceiveHandler != null)
{
logger.Log("接受到的信息 [\"" + message + "\"]");
//消息发送
DataReceiveHandler(this, message, EventArgs.Empty);
}
Array.Clear(receivedDataBuffer, 0, receivedDataBuffer.Length);
ConnectionSocket.BeginReceive(receivedDataBuffer, 0, receivedDataBuffer.Length, 0, Read, null);
}
}
catch (Exception ex)
{
logger.Log(ex.Message);
logger.Log("Socket连接将会被终止.");
MessageInfo messageInfo = new MessageInfo()
{
MsgType = MessageType.Error,
Message = ex.Message + Environment.NewLine + "Socket连接将会被终止"
};
DisconnectionHandler?.Invoke(this, JsonConvert.SerializeObject(messageInfo), EventArgs.Empty);
}
}
private byte[] BuildServerFullKey(byte[] last8Bytes)
{
byte[] concatenatedKeys = new byte[16];
Array.Copy(serverKey1, 0, concatenatedKeys, 0, 4);
Array.Copy(serverKey2, 0, concatenatedKeys, 4, 4);
Array.Copy(last8Bytes, 0, concatenatedKeys, 8, 8);
// MD5 Hash
MD5 MD5Service = MD5.Create();
return MD5Service.ComputeHash(concatenatedKeys);
}
private void BuildServerPartialKey(int keyNum, string clientKey)
{
string partialServerKey = "";
byte[] currentKey;
int spacesNum = 0;
char[] keyChars = clientKey.ToCharArray();
foreach (char currentChar in keyChars)
{
if (char.IsDigit(currentChar)) partialServerKey += currentChar;
if (char.IsWhiteSpace(currentChar)) spacesNum++;
}
try
{
currentKey = BitConverter.GetBytes((int)(Int64.Parse(partialServerKey) / spacesNum));
if (BitConverter.IsLittleEndian)
{
Array.Reverse(currentKey);
}
if (keyNum == 1)
{
serverKey1 = currentKey;
}
else
{
serverKey2 = currentKey;
}
}
catch
{
if (serverKey1 != null)
{
Array.Clear(serverKey1, 0, serverKey1.Length);
}
if (serverKey2 != null)
{
Array.Clear(serverKey2, 0, serverKey2.Length);
}
}
}
private string ComputeWebSocketHandshakeSecurityHash09(string secWebSocketKey)
{
const String MagicKEY = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
String secWebSocketAccept = String.Empty;
// 1. Combine the request Sec-WebSocket-Key with magic key.
String ret = secWebSocketKey + MagicKEY;
// 2. Compute the SHA1 hash
SHA1 sha = new SHA1CryptoServiceProvider();
byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret));
// 3. Base64 encode the hash
secWebSocketAccept = Convert.ToBase64String(sha1Hash);
return secWebSocketAccept;
}
}
}
数据文件相关的类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebSocketsServer
{
public class DataFrame
{
DataFrameHeader _header;
private byte[] _extend = new byte[0];
private byte[] _mask = new byte[0];
private byte[] _content = new byte[0];
public DataFrame(byte[] buffer)
{
//帧头
_header = new DataFrameHeader(buffer);
//扩展长度
if (_header.Length == 126)
{
_extend = new byte[2];
Buffer.BlockCopy(buffer, 2, _extend, 0, 2);
}
else if (_header.Length == 127)
{
_extend = new byte[8];
Buffer.BlockCopy(buffer, 2, _extend, 0, 8);
}
//是否有掩码
if (_header.HasMask)
{
_mask = new byte[4];
Buffer.BlockCopy(buffer, _extend.Length + 2, _mask, 0, 4);
}
//消息体
if (_extend.Length == 0)
{
_content = new byte[_header.Length];
Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + 2, _content, 0, _content.Length);
}
else if (_extend.Length == 2)
{
int contentLength = (int)_extend[0] * 256 + (int)_extend[1];
_content = new byte[contentLength];
Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + 2, _content, 0, contentLength > 1024 * 100 ? 1024 * 100 : contentLength);
}
else
{
long len = 0;
int n = 1;
for (int i = 7; i >= 0; i--)
{
len += (int)_extend[i] * n;
n *= 256;
}
_content = new byte[len];
Buffer.BlockCopy(buffer, _extend.Length + _mask.Length + 2, _content, 0, _content.Length);
}
if (_header.HasMask) _content = Mask(_content, _mask);
}
public DataFrame(string content)
{
_content = Encoding.UTF8.GetBytes(content);
int length = _content.Length;
if (length < 126)
{
_extend = new byte[0];
_header = new DataFrameHeader(true, false, false, false, 1, false, length);
}
else if (length < 65536)
{
_extend = new byte[2];
_header = new DataFrameHeader(true, false, false, false, 1, false, 126);
_extend[0] = (byte)(length / 256);
_extend[1] = (byte)(length % 256);
}
else
{
_extend = new byte[8];
_header = new DataFrameHeader(true, false, false, false, 1, false, 127);
int left = length;
int unit = 256;
for (int i = 7; i > 1; i--)
{
_extend[i] = (byte)(left % unit);
left = left / unit;
if (left == 0)
break;
}
}
}
public byte[] GetBytes()
{
byte[] buffer = new byte[2 + _extend.Length + _mask.Length + _content.Length];
Buffer.BlockCopy(_header.GetBytes(), 0, buffer, 0, 2);
Buffer.BlockCopy(_extend, 0, buffer, 2, _extend.Length);
Buffer.BlockCopy(_mask, 0, buffer, 2 + _extend.Length, _mask.Length);
Buffer.BlockCopy(_content, 0, buffer, 2 + _extend.Length + _mask.Length, _content.Length);
return buffer;
}
public string Text
{
get
{
if (_header.OpCode != 1)
return string.Empty;
return Encoding.UTF8.GetString(_content);
}
}
private byte[] Mask(byte[] data, byte[] mask)
{
for (var i = 0; i < data.Length; i++)
{
data[i] = (byte)(data[i] ^ mask[i % 4]);
}
return data;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebSocketsServer
{
public class DataFrameHeader
{
private bool _fin;
private bool _rsv1;
private bool _rsv2;
private bool _rsv3;
private sbyte _opcode;
private bool _maskcode;
private sbyte _payloadlength;
public bool FIN { get { return _fin; } }
public bool RSV1 { get { return _rsv1; } }
public bool RSV2 { get { return _rsv2; } }
public bool RSV3 { get { return _rsv3; } }
public sbyte OpCode { get { return _opcode; } }
public bool HasMask { get { return _maskcode; } }
public sbyte Length { get { return _payloadlength; } }
public DataFrameHeader(byte[] buffer)
{
if (buffer.Length < 2)
throw new Exception("无效的数据头.");
//第一个字节
_fin = (buffer[0] & 0x80) == 0x80;
_rsv1 = (buffer[0] & 0x40) == 0x40;
_rsv2 = (buffer[0] & 0x20) == 0x20;
_rsv3 = (buffer[0] & 0x10) == 0x10;
_opcode = (sbyte)(buffer[0] & 0x0f);
//第二个字节
_maskcode = (buffer[1] & 0x80) == 0x80;
_payloadlength = (sbyte)(buffer[1] & 0x7f);
}
//发送封装数据
public DataFrameHeader(bool fin, bool rsv1, bool rsv2, bool rsv3, sbyte opcode, bool hasmask, int length)
{
_fin = fin;
_rsv1 = rsv1;
_rsv2 = rsv2;
_rsv3 = rsv3;
_opcode = opcode;
//第二个字节
_maskcode = hasmask;
_payloadlength = (sbyte)length;
}
//返回帧头字节
public byte[] GetBytes()
{
byte[] buffer = new byte[2] { 0, 0 };
if (_fin) buffer[0] ^= 0x80;
if (_rsv1) buffer[0] ^= 0x40;
if (_rsv2) buffer[0] ^= 0x20;
if (_rsv3) buffer[0] ^= 0x10;
buffer[0] ^= (byte)_opcode;
if (_maskcode) buffer[1] ^= 0x80;
buffer[1] ^= (byte)_payloadlength;
return buffer;
}
}
}
自定义的枚举,实体,封装客户端输出类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebSocketsServer
{
public enum MessageType
{
Error = -1,
None = 0,
///
/// 登录
///
Login = 1,
///
/// 退出
///
Logout = 2,
///
/// 聊天消息
///
ChatInfo = 3,
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebSocketsServer
{
public class MessageInfo
{
///
/// 唯一标识
///
public Guid Identity { get; set; }
///
/// 用户名
///
public string UserName { get; set; }
///
/// 消息类型
///
public MessageType MsgType { get; set; }
///
/// 发送信息
///
public string Message { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebSocketsServer
{
public class Logger
{
public bool LogEvents { get; set; }
public Logger()
{
LogEvents = true;
}
public void Log(string Text)
{
if (LogEvents) Console.WriteLine(Text);
}
}
}
Program类的实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
///
/// WebSocket服务端
///
namespace WebSocketsServer
{
class Program
{
static void Main(string[] args)
{
WebSocketServer server = new WebSocketServer();
server.StartServer();
Console.ReadKey();
}
}
}
HTML页面实现代码如下(客户端)
WebSocket聊天室
完结:
挺有趣的事情,希望熬夜不猝死了,哈哈