C#WebSocket 채팅방

11956 단어 수계Socket
C# Socket 내용
이 장은 Socket 비동기 채팅방에 따라 WebSocket 채팅방으로 수정한다
웹소켓의 특별한 점은 악수와 메시지 내용의 인코딩, 디코딩(ServerHelper 협조 처리 추가)이다.
ServerHelper:
using System;
using System.Collections;
using System.Text;
using System.Security.Cryptography;

namespace SocketDemo
{
    // Server     :1    2      3     
    class ServerHelper
    {
        /// 
        ///        
        /// 
        public static string ResponseHeader(string requestHeader)
        {
            Hashtable table = new Hashtable();

            //       ,      
            string[] rows = requestHeader.Split(new string[] { "\r
" }, StringSplitOptions.RemoveEmptyEntries); foreach (string row in rows) { int splitIndex = row.IndexOf(':'); if (splitIndex > 0) { table.Add(row.Substring(0, splitIndex).Trim(), row.Substring(splitIndex + 1).Trim()); } } StringBuilder header = new StringBuilder(); header.Append("HTTP/1.1 101 Web Socket Protocol Handshake\r
"); header.AppendFormat("Upgrade: {0}\r
", table.ContainsKey("Upgrade") ? table["Upgrade"].ToString() : string.Empty); header.AppendFormat("Connection: {0}\r
", table.ContainsKey("Connection") ? table["Connection"].ToString() : string.Empty); header.AppendFormat("WebSocket-Origin: {0}\r
", table.ContainsKey("Sec-WebSocket-Origin") ? table["Sec-WebSocket-Origin"].ToString() : string.Empty); header.AppendFormat("WebSocket-Location: {0}\r
", table.ContainsKey("Host") ? table["Host"].ToString() : string.Empty); string key = table.ContainsKey("Sec-WebSocket-Key") ? table["Sec-WebSocket-Key"].ToString() : string.Empty; string magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; header.AppendFormat("Sec-WebSocket-Accept: {0}\r
", Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + magic)))); header.Append("\r
"); return header.ToString(); } /// /// /// public static string DecodeMsg(Byte[] buffer, int len) { if (buffer[0] != 0x81 || (buffer[0] & 0x80) != 0x80 || (buffer[1] & 0x80) != 0x80) { return null; } Byte[] mask = new Byte[4]; int beginIndex = 0; int payload_len = buffer[1] & 0x7F; if (payload_len == 0x7E) { Array.Copy(buffer, 4, mask, 0, 4); payload_len = payload_len & 0x00000000; payload_len = payload_len | buffer[2]; payload_len = (payload_len << 8) | buffer[3]; beginIndex = 8; } else if (payload_len != 0x7F) { Array.Copy(buffer, 2, mask, 0, 4); beginIndex = 6; } for (int i = 0; i < payload_len; i++) { buffer[i + beginIndex] = (byte)(buffer[i + beginIndex] ^ mask[i % 4]); } return Encoding.UTF8.GetString(buffer, beginIndex, payload_len); } /// /// /// public static byte[] EncodeMsg(string content) { byte[] bts = null; byte[] temp = Encoding.UTF8.GetBytes(content); if (temp.Length < 126) { bts = new byte[temp.Length + 2]; bts[0] = 0x81; bts[1] = (byte)temp.Length; Array.Copy(temp, 0, bts, 2, temp.Length); } else if (temp.Length < 0xFFFF) { bts = new byte[temp.Length + 4]; bts[0] = 0x81; bts[1] = 126; bts[2] = (byte)(temp.Length & 0xFF); bts[3] = (byte)(temp.Length >> 8 & 0xFF); Array.Copy(temp, 0, bts, 4, temp.Length); } else { byte[] st = System.Text.Encoding.UTF8.GetBytes(string.Format(" ").ToCharArray()); } return bts; } } }
Server:
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace SocketDemo
{
    class ClientInfo
    {
        public Socket Socket { get; set; }
        public bool IsOpen { get; set; }
        public string Address { get; set; }
    }

    //   Client
    class ClientManager
    {
        static List clientList = new List();
        public static void Add(ClientInfo info)
        {
            if (!IsExist(info.Address))
            {
                clientList.Add(info);
            }
        }
        public static bool IsExist(string address)
        {
            return clientList.Exists(item => string.Compare(address, item.Address, true) == 0);
        }
        public static bool IsExist(string address, bool isOpen)
        {
            return clientList.Exists(item => string.Compare(address, item.Address, true) == 0 && item.IsOpen == isOpen);
        }
        public static void Open(string address)
        {
            clientList.ForEach(item =>
            {
                if (string.Compare(address, item.Address, true) == 0)
                {
                    item.IsOpen = true;
                }
            });
        }
        public static void Close(string address = null)
        {
            clientList.ForEach(item =>
            {
                if (address == null || string.Compare(address, item.Address, true) == 0)
                {
                    item.IsOpen = false;
                    item.Socket.Shutdown(SocketShutdown.Both);
                }
            });
        }
        //      ClientList
        public static void SendMsgToClientList(string msg, string address = null)
        {
            clientList.ForEach(item =>
            {
                if (item.IsOpen && (address == null || item.Address != address))
                {
                    SendMsgToClient(item.Socket, msg);
                }
            });
        }
        public static void SendMsgToClient(Socket client, string msg)
        {
            byte[] bt = ServerHelper.EncodeMsg(msg);
            client.BeginSend(bt, 0, bt.Length, SocketFlags.None, new AsyncCallback(SendTarget), client);
        }
        private static void SendTarget(IAsyncResult res)
        {
            //Socket client = (Socket)res.AsyncState;
            //int size = client.EndSend(res);
        }
    }

    //     
    class ReceiveHelper
    {
        public byte[] Bytes { get; set; }
        public void ReceiveTarget(IAsyncResult res)
        {
            Socket client = (Socket)res.AsyncState;
            int size = client.EndReceive(res);
            if (size > 0)
            {
                string address = client.RemoteEndPoint.ToString(); //   Client IP   
                string stringdata = 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 + "       ", address);
                    ClientManager.Close(address);
                    Console.WriteLine(address + "       ");
                    Console.WriteLine(address + " " + DateTimeOffset.Now.ToString("G"));
                    return;
                }
                else
                {
                    Console.WriteLine(stringdata);
                    Console.WriteLine(address + " " + DateTimeOffset.Now.ToString("G"));
                    ClientManager.SendMsgToClientList(stringdata, address);
                }
            }
            //     
            client.BeginReceive(Bytes, 0, Bytes.Length, SocketFlags.None, new AsyncCallback(ReceiveTarget), client);
        }
    }

    //     
    class AcceptHelper
    {
        public byte[] Bytes { get; set; }

        public void AcceptTarget(IAsyncResult res)
        {
            Socket server = (Socket)res.AsyncState;
            Socket client = server.EndAccept(res);
            string address = client.RemoteEndPoint.ToString();

            ClientManager.Add(new ClientInfo() { Socket = client, Address = address, IsOpen = false });
            ReceiveHelper rs = new ReceiveHelper() { Bytes = this.Bytes };
            IAsyncResult recres = client.BeginReceive(rs.Bytes, 0, rs.Bytes.Length, SocketFlags.None, new AsyncCallback(rs.ReceiveTarget), client);
            //     
            server.BeginAccept(new AsyncCallback(AcceptTarget), server);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            server.Bind(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 200)); //   IP+  
            server.Listen(10); //     

            Console.WriteLine("    ...");

            AcceptHelper ca = new AcceptHelper() { Bytes = new byte[2048] };
            IAsyncResult res = server.BeginAccept(new AsyncCallback(ca.AcceptTarget), server);

            string str = string.Empty;
            while (str != "exit")
            {
                str = Console.ReadLine();
                Console.WriteLine("ME: " + DateTimeOffset.Now.ToString("G"));
                ClientManager.SendMsgToClientList(str);
            }
            ClientManager.Close();
            server.Close();
        }
    }
}
Client:


    var mySocket;
    function Star() {
        mySocket = new WebSocket("ws://127.0.0.1:200", "my-custom-protocol");
        mySocket.onopen = function Open() {
            Show("    ");
        };
        mySocket.onmessage = function (evt) {
            Show(evt.data);
        };
        mySocket.onclose = function Close() {
            Show("    ");
            mySocket.close();
        };
    }
    function Send() {
        var content = document.getElementById("content").value;
        Show(content);
        mySocket.send(content);
    }
    function Show(msg) {
        var roomContent = document.getElementById("roomContent");
        roomContent.innerHTML = msg + "<br/>" + roomContent.innerHTML;
    }



    


    <div id="roomContent" style="width: 500px; height: 200px; overflow: hidden; border: 2px solid #686868;
        margin-bottom: 10px; padding: 10px 0px 0px 10px;">
    </div>
    <div>
        <textarea id="content" cols="50" rows="3" style="padding: 10px 0px 0px 10px;"/>
    </div>
    <input type="button" value="Connection"/>
    <input type="button" value="Send"/>


</code></pre> 
  <br/> 
  <p><br/></p> 
 </div> 
</div>
                            </div>
                        </div>

좋은 웹페이지 즐겨찾기