zoukankan      html  css  js  c++  java
  • c# websocket 服务端,客户端 兼容低版本IE,支持超长数据传输 附源码

    服务端:

      1 namespace WebSocketServerEx
      2 {
      3     public class OpCode
      4     {
      5         public const sbyte Plain = -2; // defined by SuperWebSocket, to support hybi-00
      6         public const string PlainTag = "-2";
      7 
      8         public const sbyte Handshake = -1; // defined by SuperWebSocket
      9         public const string HandshakeTag = "-1";
     10 
     11         public const sbyte Continuation = 0;
     12         public const string ContinuationTag = "0";
     13 
     14         public const sbyte Text = 1;
     15         public const string TextTag = "1";
     16 
     17         public const sbyte Binary = 2;
     18         public const string BinaryTag = "2";
     19 
     20         public const sbyte Close = 8;
     21         public const string CloseTag = "8";
     22 
     23         public const sbyte Ping = 9;
     24         public const string PingTag = "9";
     25 
     26         public const sbyte Pong = 10;
     27         public const string PongTag = "10";
     28     }
     29 
     30     public partial class Form1 : Form
     31     {
     32         private Thread thMain = null;
     33         private Thread thFlashServer = null;
     34         private Thread thClear = null;
     35         private Dictionary<string, TcpClient> listMainTcp = new Dictionary<string, TcpClient>();
     36         private List<TcpClient> listFlashTcp = new List<TcpClient>();
     37         private Dictionary<string, Thread> listths = new Dictionary<string, Thread>();
     38 
     39         private ManualResetEvent tcpClientConnected = new ManualResetEvent(false);
     40         private ManualResetEvent tcpClientConnectedflash = new ManualResetEvent(false);
     41 
     42         public bool IsOnline(TcpClient c)
     43         {
     44             return !((c.Client.Poll(1000, SelectMode.SelectRead) && (c.Client.Available == 0)) || !c.Client.Connected);
     45         }
     46         public Form1()
     47         {
     48             InitializeComponent();
     49         }
     50 
     51         private void Form1_Load(object sender, EventArgs e)
     52         {
     53             txtIP.Text = GetLocalIP();
     54             txtPort.Text = "8888";
     55         }
     56 
     57         private void WebSocketMain()
     58         {
     59             //实例化服务器本机的端点
     60             IPEndPoint local = new IPEndPoint(IPAddress.Parse(txtIP.Text), Convert.ToInt32(txtPort.Text));
     61             //定义服务器监听对象
     62             TcpListener listener = new TcpListener(local);
     63             //开始监听
     64             listener.Start();
     65 
     66             thMain = new Thread(() =>
     67             {
     68                 while (true)
     69                 {
     70                     try
     71                     {
     72                         tcpClientConnected.Reset();
     73                         listener.BeginAcceptTcpClient(clientConnect, listener);
     74                         tcpClientConnected.WaitOne();
     75                     }
     76                     catch (Exception ex)
     77                     {
     78                         WriteLog("Error", "WebSocketMain " + ex.Message);
     79                     }
     80                 }
     81             });
     82 
     83             thMain.Start();
     84         }
     85 
     86         private void clientConnect(IAsyncResult ar)
     87         {
     88             try
     89             {
     90                 TcpListener listener = (TcpListener)ar.AsyncState;
     91                 //接受客户的连接,得到连接的Socket
     92                 TcpClient client = listener.EndAcceptTcpClient(ar);
     93                 client.ReceiveBufferSize = 524288;
     94                 client.SendBufferSize = 524288;
     95                 Console.WriteLine("t " + client.Available);
     96                 int maxi = 0;
     97                 while (IsOnline(client) && maxi <= 1000)
     98                 {
     99                     maxi++;
    100                     Console.WriteLine("max " + maxi);
    101                     if (client.Available > 0)
    102                     {
    103                         BinaryReader reader = new BinaryReader(client.GetStream());
    104                         BinaryWriter writer = new BinaryWriter(client.GetStream());
    105 
    106                         Console.WriteLine("33");
    107 
    108                         byte[] buffer = new byte[client.Available];
    109                         reader.Read(buffer, 0, client.Available);
    110                         String result = Encoding.UTF8.GetString(buffer);
    111                         if (result.IndexOf("Sec-WebSocket-Key") >= 0)
    112                         {
    113                             writer.Write(PackHandShakeData(GetSecKeyAccetp(result)));
    114                             writer.Flush();
    115 
    116                             lock (listMainTcp)
    117                             {
    118                                 if (!listMainTcp.ContainsValue(client))
    119                                 {
    120                                     listMainTcp.Add(client.Client.RemoteEndPoint.ToString(), client);
    121                                 }
    122                             }
    123 
    124                             cmbClient.Invoke(new Action(() =>
    125                             {
    126                                 cmbClient.Items.Add(client.Client.RemoteEndPoint.ToString());
    127                             }));
    128 
    129                             WriteLog("Info", "websocket 握手成功!" + client.Client.RemoteEndPoint);
    130                         }
    131 
    132                         Thread th = new Thread(() =>
    133                         {
    134                             while (true)
    135                             {
    136                                 try
    137                                 {
    138                                     if (client.Available > 0)
    139                                     {
    140                                         byte[] buffers = new byte[client.Available];
    141                                         reader.Read(buffers, 0, client.Available);
    142                                         result = AnalyticData(buffers, buffers.Length);
    143                                         WriteLog("Info", "来自客户端[" + client.Client.RemoteEndPoint + "]消息" + result);
    144 
    145                                         if (result == "u0003�")
    146                                         {
    147                                             lock (listMainTcp)
    148                                             {
    149                                                 listMainTcp.Remove(client.Client.RemoteEndPoint.ToString());
    150                                             }
    151                                             lock (listths)
    152                                             {
    153                                                 listths.Remove(client.Client.RemoteEndPoint.ToString());
    154                                             }
    155                                             client.Close();
    156                                             break;
    157                                         }
    158                                     }
    159                                 }
    160                                 catch (ThreadAbortException e)
    161                                 {
    162 
    163                                 }
    164                                 catch (Exception ex)
    165                                 {
    166                                     WriteLog("Error", "th " + ex.Message);
    167                                 }
    168                             }
    169                         });
    170                         th.Name = client.Client.RemoteEndPoint.ToString();
    171                         listths.Add(th.Name, th);
    172                         th.Start();
    173 
    174                         break;
    175                     }
    176                 }
    177             }
    178             catch
    179             {
    180             }
    181             finally
    182             {
    183                 tcpClientConnected.Set();
    184             }
    185         }
    186 
    187         private void FlashSocketServer()
    188         {
    189             //实例化服务器本机的端点
    190             IPEndPoint local = new IPEndPoint(IPAddress.Parse(txtIP.Text), 843);
    191             //定义服务器监听对象
    192             TcpListener listener = new TcpListener(local);
    193             //开始监听
    194             listener.Start();
    195 
    196             TcpClient client = null;
    197             BinaryReader reader = null;
    198             BinaryWriter writer = null;
    199             thFlashServer = new Thread(() =>
    200             {
    201                 while (true)
    202                 {
    203                     try
    204                     {
    205                         client = listener.AcceptTcpClient();
    206                         Console.WriteLine("1 t" + client.Available);
    207                         int maxi = 0;
    208                         while (IsOnline(client) && maxi <= 1000)
    209                         {
    210                             maxi++;
    211                             Console.WriteLine("max2 " + maxi);
    212                             if (client.Available > 0)
    213                             {
    214                                 lock (listFlashTcp)
    215                                 {
    216                                     if (!listFlashTcp.Contains(client))
    217                                     {
    218                                         listFlashTcp.Add(client);
    219                                     }
    220                                 }
    221 
    222                                 reader = new BinaryReader(client.GetStream());
    223                                 writer = new BinaryWriter(client.GetStream());
    224 
    225 
    226                                 byte[] buffer = new byte[client.Available];
    227                                 reader.Read(buffer, 0, client.Available);
    228                                 String result = Encoding.UTF8.GetString(buffer);
    229                                 if (result.IndexOf("<policy-file-request/>") >= 0)
    230                                 {
    231                                     byte[] datas = System.Text.Encoding.UTF8.GetBytes("<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>");
    232                                     writer.Write(datas);
    233                                     writer.Flush();
    234                                     WriteLog("Info", "843端口握手成功!" + client.Client.RemoteEndPoint);
    235                                 }
    236 
    237                                 break;
    238                             }
    239                         }
    240                     }
    241                     catch (Exception ex)
    242                     {
    243                         WriteLog("Error", "thFlashServer " + ex.Message);
    244                     }
    245                 }
    246             });
    247             thFlashServer.Start();
    248         }
    249 
    250         private void tClear()
    251         {
    252             thClear = new Thread(() =>
    253             {
    254                 while (true)
    255                 {
    256                     Thread.Sleep(10000);
    257 
    258                     try
    259                     {
    260                         lock (listMainTcp)
    261                         {
    262                             if (listMainTcp.Count > 0)
    263                             {
    264                                 string[] keys = new string[listMainTcp.Count];
    265                                 listMainTcp.Keys.CopyTo(keys, 0);
    266                                 foreach (string key in keys)
    267                                 {
    268                                     if (listMainTcp[key] != null)
    269                                     {
    270                                         if (!IsOnline(listMainTcp[key]))
    271                                         {
    272                                             listths[key].Abort();
    273                                             listths.Remove(key);
    274 
    275                                             cmbClient.Invoke(new Action(() =>
    276                                             {
    277                                                 cmbClient.Items.Remove(key);
    278                                             }));
    279 
    280                                             listMainTcp[key].Close();
    281                                             listMainTcp[key] = null;
    282                                             listMainTcp.Remove(key);
    283                                         }
    284                                     }
    285                                 }
    286                             }
    287                         }
    288 
    289                         lock (listFlashTcp)
    290                         {
    291                             if (listFlashTcp.Count > 0)
    292                             {
    293                                 for (int i = 0; i < listFlashTcp.Count; i++)
    294                                 {
    295                                     if (listFlashTcp[i] != null)
    296                                     {
    297                                         if (!IsOnline(listFlashTcp[i]))
    298                                         {
    299                                             listFlashTcp[i].Close();
    300                                             listFlashTcp.Remove(listFlashTcp[i]);
    301                                         }
    302                                     }
    303                                 }
    304                             }
    305                         }
    306                     }
    307                     catch (Exception ex)
    308                     {
    309                         WriteLog("Error", "tClear " + ex.Message);
    310                     }
    311                 }
    312             });
    313             thClear.Start();
    314         }
    315 
    316         private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    317         {
    318             try
    319             {
    320                 lock (listths)
    321                 {
    322                     listths.Clear();
    323                 }
    324             }
    325             catch { }
    326 
    327             try
    328             {
    329                 thMain.Abort();
    330                 thFlashServer.Abort();
    331                 thClear.Abort();
    332 
    333                 thMain = null;
    334                 thFlashServer = null;
    335                 thClear = null;
    336             }
    337             catch { }
    338 
    339             try
    340             {
    341                 lock (listMainTcp)
    342                 {
    343                     listMainTcp.Clear();
    344                 }
    345 
    346                 lock (listFlashTcp)
    347                 {
    348                     listFlashTcp.Clear();
    349                 }
    350             }
    351             catch { }
    352         }
    353 
    354         private void Form1_FormClosing(object sender, FormClosingEventArgs e)
    355         {
    356             if (MessageBox.Show("您确定要关闭吗,关闭后相关服务不可用!", "提示", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
    357             {
    358                 e.Cancel = false;
    359             }
    360             else
    361             {
    362                 e.Cancel = true;
    363                 WriteLog("Fatal", "试图关闭本程序!");
    364             }
    365         }
    366         private void WriteLog(string type, string t)
    367         {
    368             if (!txtLog.IsDisposed)
    369             {
    370                 try
    371                 {
    372                     txtLog.Invoke(new Action(() =>
    373                     {
    374                         txtLog.AppendText(Environment.NewLine);
    375                         txtLog.AppendText(string.Format("[{0}] [{1}] {2}", type, DateTime.Now.ToString(), t));
    376                     }));
    377                 }
    378                 catch { }
    379             }
    380         }
    381 
    382         /// <summary>
    383         /// 打包握手信息
    384         /// </summary>
    385         /// <param name="secKeyAccept">Sec-WebSocket-Accept</param>
    386         /// <returns>数据包</returns>
    387         private byte[] PackHandShakeData(string secKeyAccept)
    388         {
    389             var responseBuilder = new StringBuilder();
    390             responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);
    391             responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);
    392             responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);
    393             responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine + Environment.NewLine);
    394             //如果把上一行换成下面两行,才是thewebsocketprotocol-17协议,但居然握手不成功,目前仍没弄明白!
    395             //responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine);
    396             //responseBuilder.Append("Sec-WebSocket-Protocol: chat" + Environment.NewLine);
    397 
    398             return Encoding.UTF8.GetBytes(responseBuilder.ToString());
    399         }
    400 
    401         /// <summary>
    402         /// 生成Sec-WebSocket-Accept
    403         /// </summary>
    404         /// <param name="handShakeText">客户端握手信息</param>
    405         /// <returns>Sec-WebSocket-Accept</returns>
    406         private string GetSecKeyAccetp(String handShakeText)
    407         {
    408             string key = string.Empty;
    409             Regex r = new Regex(@"Sec-WebSocket-Key:(.*?)
    ");
    410             Match m = r.Match(handShakeText);
    411             if (m.Groups.Count != 0)
    412             {
    413                 key = Regex.Replace(m.Value, @"Sec-WebSocket-Key:(.*?)
    ", "$1").Trim();
    414             }
    415             byte[] encryptionString = SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"));
    416             return Convert.ToBase64String(encryptionString);
    417         }
    418 
    419         /// <summary>
    420         /// 解析客户端数据包
    421         /// </summary>
    422         /// <param name="recBytes">服务器接收的数据包</param>
    423         /// <param name="recByteLength">有效数据长度</param>
    424         /// <returns></returns>
    425         private static string AnalyticData(byte[] recBytes, int recByteLength)
    426         {
    427             if (recByteLength < 2) { return string.Empty; }
    428 
    429             bool fin = (recBytes[0] & 0x80) == 0x80; // 1bit,1表示最后一帧  
    430             if (!fin)
    431             {
    432                 return string.Empty;// 超过一帧暂不处理 
    433             }
    434 
    435             bool mask_flag = (recBytes[1] & 0x80) == 0x80; // 是否包含掩码  
    436             if (!mask_flag)
    437             {
    438                 return string.Empty;// 不包含掩码的暂不处理
    439             }
    440 
    441             int payload_len = recBytes[1] & 0x7F; // 数据长度  
    442 
    443             byte[] masks = new byte[4];
    444             byte[] payload_data;
    445 
    446             if (payload_len == 126)
    447             {
    448                 Array.Copy(recBytes, 4, masks, 0, 4);
    449                 payload_len = (UInt16)(recBytes[2] << 8 | recBytes[3]);
    450                 payload_data = new byte[payload_len];
    451                 Array.Copy(recBytes, 8, payload_data, 0, payload_len);
    452 
    453             }
    454             else if (payload_len == 127)
    455             {
    456                 Array.Copy(recBytes, 10, masks, 0, 4);
    457                 byte[] uInt64Bytes = new byte[8];
    458                 for (int i = 0; i < 8; i++)
    459                 {
    460                     uInt64Bytes[i] = recBytes[9 - i];
    461                 }
    462                 UInt64 len = BitConverter.ToUInt64(uInt64Bytes, 0);
    463 
    464                 payload_data = new byte[len];
    465                 for (UInt64 i = 0; i < len; i++)
    466                 {
    467                     payload_data[i] = recBytes[i + 14];
    468                 }
    469             }
    470             else
    471             {
    472                 Array.Copy(recBytes, 2, masks, 0, 4);
    473                 payload_data = new byte[payload_len];
    474                 Array.Copy(recBytes, 6, payload_data, 0, payload_len);
    475 
    476             }
    477 
    478             for (var i = 0; i < payload_len; i++)
    479             {
    480                 payload_data[i] = (byte)(payload_data[i] ^ masks[i % 4]);
    481             }
    482 
    483             return Encoding.UTF8.GetString(payload_data);
    484         }
    485 
    486         private string GetLocalIP()
    487         {
    488             try
    489             {
    490                 string HostName = Dns.GetHostName(); //得到主机名  
    491                 IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
    492                 for (int i = 0; i < IpEntry.AddressList.Length; i++)
    493                 {
    494                     //从IP地址列表中筛选出IPv4类型的IP地址  
    495                     //AddressFamily.InterNetwork表示此IP为IPv4,  
    496                     //AddressFamily.InterNetworkV6表示此地址为IPv6类型  
    497                     if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
    498                     {
    499                         return IpEntry.AddressList[i].ToString();
    500                     }
    501                 }
    502                 return "";
    503             }
    504             catch (Exception ex)
    505             {
    506                 WriteLog("Error", "获取本机IP出错:" + ex.Message);
    507                 return "";
    508             }
    509         }
    510 
    511         /// <summary>
    512         /// 可传输超长数据
    513         /// </summary>
    514         /// <param name="opCode"></param>
    515         /// <param name="data"></param>
    516         /// <param name="offset"></param>
    517         /// <param name="length"></param>
    518         /// <returns></returns>
    519         private byte[] GetPackageData(int opCode, byte[] data, int offset, int length)
    520         {
    521             byte[] fragment;
    522 
    523             if (length < 126)
    524             {
    525                 fragment = new byte[2 + length];
    526                 fragment[1] = (byte)length;
    527             }
    528             else if (length < 65536)
    529             {
    530                 fragment = new byte[4 + length];
    531                 fragment[1] = (byte)126;
    532                 fragment[2] = (byte)(length / 256);
    533                 fragment[3] = (byte)(length % 256);
    534             }
    535             else
    536             {
    537                 fragment = new byte[10 + length];
    538                 fragment[1] = (byte)127;
    539 
    540                 int left = length;
    541                 int unit = 256;
    542 
    543                 for (int i = 9; i > 1; i--)
    544                 {
    545                     fragment[i] = (byte)(left % unit);
    546                     left = left / unit;
    547 
    548                     if (left == 0)
    549                         break;
    550                 }
    551             }
    552 
    553             fragment[0] = (byte)(opCode | 0x80);
    554 
    555             if (length > 0)
    556             {
    557                 Buffer.BlockCopy(data, offset, fragment, fragment.Length - length, length);
    558             }
    559 
    560             return fragment;
    561         }
    562 
    563         private void BtnStart_Click(object sender, EventArgs e)
    564         {
    565             WriteLog("Info", "启动 FlashSocketServer");
    566             FlashSocketServer();
    567 
    568             WriteLog("Info", "启动 WebSocketMain");
    569             WebSocketMain();
    570 
    571             WriteLog("Info", "开始监听...");
    572             tClear();
    573         }
    574 
    575         private void btnSend_Click(object sender, EventArgs e)
    576         {
    577             try
    578             {
    579                 if (cmbClient.SelectedIndex > -1)
    580                 {
    581                     TcpClient client = listMainTcp[cmbClient.SelectedItem.ToString()];
    582                     if (client != null)
    583                     {
    584                         if (IsOnline(client))
    585                         {
    586                             BinaryWriter writer = new BinaryWriter(client.GetStream());
    587                             byte[] playloadData = Encoding.UTF8.GetBytes(txtmsg.Text);
    588                             var fragment = GetPackageData(OpCode.Text, playloadData, 0, playloadData.Length);
    589                             writer.Write(fragment);
    590                         }
    591                     }
    592                 }
    593             }
    594             catch (Exception ex)
    595             {
    596                 WriteLog("Error", "send " + ex.Message);
    597             }
    598         }
    599     }
    600 }

    客户端:

    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Sample of web_socket.js</title>
    
        <!-- Include these three JS files: -->
        <script type="text/javascript" src="swfobject.js"></script>
        <script type="text/javascript" src="web_socket.js"></script>
    
        <script type="text/javascript">
    
            // Set URL of your WebSocketMain.swf here:
            WEB_SOCKET_SWF_LOCATION = "WebSocketMain.swf";
            // Set this to dump debug message from Flash to console.log:
            WEB_SOCKET_DEBUG = true;
    
            // Everything below is the same as using standard WebSocket.
    
            var ws;
    
            function init() {
    
                // Connect to Web Socket.
                // Change host/port here to your own Web Socket server.
                ws = new WebSocket("ws://127.0.0.1:8888/");
    
                // Set event handlers.
                ws.onopen = function () {
                    output("onopen");
                };
                ws.onmessage = function (e) {
                    // e.data contains received string.
                    output("onmessage: " + e.data);
                };
                ws.onclose = function () {
                    output("onclose");
                };
                ws.onerror = function () {
                    output("onerror");
                };
    
            }
    
            function onSubmit() {
                var input = document.getElementById("input");
                // You can send message to the Web Socket using ws.send.
                ws.send(input.value);
                output("send: " + input.value);
                input.value = "";
                input.focus();
            }
    
            function onCloseClick() {
                ws.close();
            }
    
            function output(str) {
                var log = document.getElementById("log");
                var escaped = str.replace(/&/, "&amp;").replace(/</, "&lt;").
                  replace(/>/, "&gt;").replace(/"/, "&quot;"); // "
                log.innerHTML = escaped + "<br>" + log.innerHTML;
            }
    
      </script>
    </head>
    <body onload="init();">
        <form onsubmit="onSubmit(); return false;">
            <input type="text" id="input">
            <input type="submit" value="Send">
            <button onclick="onCloseClick(); return false;">close</button>
        </form>
        <div id="log"></div>
    </body>
    </html>

    服务端源码:http://files.cnblogs.com/files/diose/WebSocketServerEx.zip

    客户端源码:http://files.cnblogs.com/files/diose/ClientWebsocketDemo.zip

    如技术问题可以咨询:QQ 598181863

  • 相关阅读:
    需学习
    CentOS中一些基本的操作记录
    允许IIS下载无后缀文件及“请求的内容似乎是脚本,因而将无法由静态文件处理程序来处理。”的解决方法
    sql server使用的注意点及优化点 自备
    kali 系列学习02
    kali 系列学习01
    运维自动化之13
    运维自动化之12
    运维自动化之11
    运维自动化之10
  • 原文地址:https://www.cnblogs.com/diose/p/7345879.html
Copyright © 2011-2022 走看看