using System; using System.Collections.Generic; using System.Text; using System.Net; using System.Net.Sockets; using System.IO; using System.Collections; namespace SocketSrv { //控制台输出日志 //public class Logger //{ // public bool LogEvents { get; set; } // public Logger() // { // LogEvents = true; // } // public void Log(string Text) // { // if (LogEvents) Console.WriteLine(Text); // } //} public enum ServerStatusLevel { Off, WaitingConnection, ConnectionEstablished }; public delegate void NewConnectionEventHandler(Object sender,string loginName,EventArgs e); public delegate void DataReceivedEventHandler(Object sender, string message, EventArgs e); public delegate void DisconnectedEventHandler(Object sender,EventArgs e); public delegate void BroadcastEventHandler(string message, EventArgs e); public class WebSocketServer : IDisposable { private bool AlreadyDisposed; private Socket Listener; private int ConnectionsQueueLength; private int MaxBufferSize; private string Handshake; private StreamReader ConnectionReader; private StreamWriter ConnectionWriter; // private Logger logger; private byte[] FirstByte; private byte[] LastByte; private byte[] ServerKey1; private byte[] ServerKey2; private Hashtable onlineList; List connectionSocketList = new List(); public ServerStatusLevel Status { get; private set; } public int ServerPort { get; set; } public string ServerLocation { get; set; } public string ConnectionOrigin { get; set; } //public bool LogEvents { // get { return logger.LogEvents; } // set { logger.LogEvents = value; } //} public event NewConnectionEventHandler NewConnection; public event DataReceivedEventHandler DataReceived; public event DisconnectedEventHandler Disconnected; private void Initialize() { AlreadyDisposed = false; // logger = new Logger(); Status = ServerStatusLevel.Off; ConnectionsQueueLength = 500; MaxBufferSize = 1024 * 100; FirstByte = new byte[MaxBufferSize]; LastByte = new byte[MaxBufferSize]; FirstByte[0] = 0x00; LastByte[0] = 0xFF; // logger.LogEvents = true; onlineList=new Hashtable(); } //构造函数 .默认设置 public WebSocketServer() { ServerPort = 4141; ServerLocation = string.Format("ws://{0}:4141/chat", "192.168.0.102"); Initialize(); } //构造函数 . 用户设置 public WebSocketServer(int serverPort, string serverLocation, string connectionOrigin) { ServerPort = serverPort; ConnectionOrigin = connectionOrigin; ServerLocation = serverLocation; Initialize(); } ~WebSocketServer() { Close(); } public void Dispose() { Close(); } //服务关闭 private void Close() { if (!AlreadyDisposed) { AlreadyDisposed = true; if (Listener != null) Listener.Close(); foreach (SocketConnection item in connectionSocketList) { item.ConnectionSocket.Close(); } connectionSocketList.Clear(); GC.SuppressFinalize(this); } } //获取本机IP //public static IPAddress getLocalmachineIPAddress() //{ // string strHostName = Dns.GetHostName(); // IPHostEntry ipEntry = Dns.GetHostEntry(strHostName); // foreach (IPAddress ip in ipEntry.AddressList) // { // //IPV4 // if (ip.AddressFamily == AddressFamily.InterNetwork) // return ip; // } // return ipEntry.AddressList[0]; //} //服务器开始运行 监听 public void StartServer() { Char char1 = Convert.ToChar(65533); Listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP); Listener.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.102"), ServerPort)); Listener.Listen(ConnectionsQueueLength); //logger.Log(string.Format("聊天服务器启动。监听地址:{0}, 端口:{1}",getLocalmachineIPAddress(),ServerPort)); //logger.Log(string.Format("WebSocket服务器地址: ws://{0}:{1}/chat", getLocalmachineIPAddress(), ServerPort)); //等待客户端连接 while (true) { Socket sc = Listener.Accept(); if (sc != null) { System.Threading.Thread.Sleep(100); SocketConnection socketConn = new SocketConnection(); socketConn.ConnectionSocket = sc; socketConn.NewConnection += new NewConnectionEventHandler(socketConn_NewConnection); socketConn.DataReceived += new DataReceivedEventHandler(socketConn_BroadcastMessage); socketConn.Disconnected += new DisconnectedEventHandler(socketConn_Disconnected); socketConn.ConnectionSocket.BeginReceive(socketConn.receivedDataBuffer, 0, socketConn.receivedDataBuffer.Length, 0, new AsyncCallback(socketConn.ManageHandshake), socketConn.ConnectionSocket.Available); //保存每一个连接的客户端 connectionSocketList.Add(socketConn); } } } //客户端断开连接 void socketConn_Disconnected(Object sender, EventArgs e) { SocketConnection sConn = sender as SocketConnection; if (sConn != null) { //重新发送在线用户列表 onlineList.Remove(sConn.Id); Send("onLineList:" + GetOnlineName()); //关闭和移除该客户端 sConn.ConnectionSocket.Close(); connectionSocketList.Remove(sConn); } } //客户端消息传递 void socketConn_BroadcastMessage(Object sender, string message, EventArgs e) { //服务器中转信息 SendChat(message); } //新的用户连接 void socketConn_NewConnection(Object sender,string message, EventArgs e) { SocketConnection sConn = sender as SocketConnection; string idName = message.Replace( "login:",""); sConn.Id = idName.Split(',')[0]; sConn.Name = idName.Split(',')[1]; if (!onlineList.ContainsKey(sConn.Id)) { //保存到在线列表 onlineList[sConn.Id] = sConn; } //发送在线列表 Send("onLineList:" + GetOnlineName()); } //获取在线列表的用户名和ID 格式为 id|name,id|name,id|name private string GetOnlineName() { string names = string.Empty; foreach (SocketConnection sc in onlineList.Values) { names += sc.Id+"|"+ sc.Name + ","; } return names.TrimEnd(','); } //服务器群发消息 public void Send(string message) { foreach (SocketConnection item in connectionSocketList) { if (!item.ConnectionSocket.Connected) return; try { if (item.IsDataMasked) { DataFrame dr = new DataFrame(message); item.ConnectionSocket.Send(dr.GetBytes()); } else { item.ConnectionSocket.Send(FirstByte); item.ConnectionSocket.Send(Encoding.UTF8.GetBytes(message)); item.ConnectionSocket.Send(LastByte); } } catch(Exception ex) { //logger.Log(ex.Message); } } } //服务器转发消息 public void SendChat(string message) { string[] info = message.Split('|'); foreach (SocketConnection item in onlineList.Values) { if (!item.ConnectionSocket.Connected) continue; if (item.Id != info[0])continue; //找到需要转发的对象 string newMsg = info[1] + "|" + info[2]; try { if (item.IsDataMasked) { DataFrame dr = new DataFrame(newMsg); item.ConnectionSocket.Send(dr.GetBytes()); } else { item.ConnectionSocket.Send(FirstByte); item.ConnectionSocket.Send(Encoding.UTF8.GetBytes(newMsg)); item.ConnectionSocket.Send(LastByte); } } catch (Exception ex) { //logger.Log(ex.Message); } } } } }