首页 新闻 会员 周边

使用C#实现websocket 服务器问题

1
悬赏园豆:50 [已解决问题] 解决于 2012-08-24 15:59

我的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Security.Cryptography;
using System.IO;

namespace ConsoleService
{
    class Program
    {
        static AutoResetEvent allDone = new AutoResetEvent(false);

        static void Main(string[] args)
        {
            IPEndPoint localEP = new IPEndPoint(IPAddress.Parse("10.9.16.31"), 1818);

            Console.WriteLine("Local address and port : {0}", localEP.ToString());

            Socket listener = new Socket(localEP.Address.AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);

            try
            {
                listener.Bind(localEP);
                listener.Listen(500);

                
                while (true)
                {
                    Socket sc = listener.Accept();
                    if (sc != null)
                    {
                        StateObject state = new StateObject();
                        state.workSocket = sc;
                        Console.WriteLine("Waiting for a connection...");
                        sc.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);

                        allDone.WaitOne();
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            Console.WriteLine("Closing the listener...");
        }

        static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the state object and the client socket 
                // from the asynchronous state object.
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;
                Console.WriteLine("接收自:"+state.workSocket.RemoteEndPoint.ToString());

                // Read data from the remote device.
                int bytesRead = client.EndReceive(ar);
                allDone.Set();

                if (bytesRead > 0)
                {
                    System.Text.UTF8Encoding decoder = new System.Text.UTF8Encoding();
                    string browser=decoder.GetString(state.buffer,0,bytesRead);
                    Console.WriteLine(browser);

                    string key = string.Empty;

                    Regex r = new Regex(@"Sec\-WebSocket\-Key:(.*?)\r\n"); //查找"Abc"
                    Match m = r.Match(browser); //设定要查找的字符串
                    if (m.Groups.Count != 0)
                    {
                        key = Regex.Replace(m.Value, @"Sec\-WebSocket\-Key:(.*?)\r\n", "$1").Trim();
                    }
                    Console.WriteLine("获取的客户端的KEY:"+key);

                    string secKeyAccept = Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")));
                    Console.WriteLine("服务器端生成的KEY:"+secKeyAccept);

                    var responseBuilder = new StringBuilder();

                    responseBuilder.Append("HTTP/1.1 101 Switching Protocols" + Environment.NewLine);
                    responseBuilder.Append("Upgrade: websocket" + Environment.NewLine);
                    responseBuilder.Append("Connection: Upgrade" + Environment.NewLine);
                    responseBuilder.Append("Sec-WebSocket-Accept: " + secKeyAccept + Environment.NewLine);
                    responseBuilder.Append("Sec-WebSocket-Protocol: chat" + Environment.NewLine);

                    Console.WriteLine("服务器端欲发送信息:\r\n"+responseBuilder.ToString());

                    byte[] HandshakeText = Encoding.UTF8.GetBytes(responseBuilder.ToString());


                    state.workSocket.BeginSend(HandshakeText, 0, HandshakeText.Length, 0, new AsyncCallback(SendCallback), state);
                    

                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        static void SendCallback(IAsyncResult ar) {
            StateObject state = (StateObject)ar.AsyncState;
            Socket client = state.workSocket;
            client.EndSend(ar);

            Console.WriteLine("发送至:" + state.workSocket.RemoteEndPoint.ToString()+" 结束。");
            Console.WriteLine("本应该握手成功的?!");

            
            //byte[] msg = Encoding.UTF8.GetBytes("hello");
            //state.workSocket.Send(msg);
        }

    }
    public class StateObject
    {
        public Socket workSocket = null;
        public const int BufferSize = 1024;
        public byte[] buffer = new byte[BufferSize];
        public StringBuilder sb = new StringBuilder();
    }
}

HTML代码:

<html>
<head>
    <meta charset="UTF-8">
    <title>Web sockets test</title>
    <script src="jquery-min.js" type="text/javascript"></script>
    <script type="text/javascript">
        var ws;

        function ToggleConnectionClicked() {          
                try {
                    ws = new WebSocket("ws://10.9.16.31:1818/chat");        
                    
                    ws.onopen = function(event){alert("连接已经建立:"+this.readyState);};
                    ws.onmessage = function(event){alert("接收到的数据:"+event.data);};
                    ws.onclose = function(event){alert("断开,信息:"+this.readyState);};
                    ws.onerror = function(event){alert("错误"+event.message);};
                } catch (ex) {
                    alert(ex.message);      
                }
                //document.getElementById("ToggleConnection").innerHTML = "断开";
        };

        function SendData() {
            try{
                ws.send("hello");
            }catch(ex){
                alert(ex.message);
            }
        };

         function close() {
            try{
                ws.close();
                ws=null;
            }catch(ex){
                alert(ex.message);
            }
        };

        function seestate(){
            alert(ws.readyState);
        }
       
    </script>
</head>
<body>
   <button id='ToggleConnection' type="button" onclick='ToggleConnectionClicked();'>连接</button><br />
    <button id='ToggleConnection' type="button" onclick='SendData();'>发送</button><br />
    <button id='ToggleConnection' type="button" onclick='close();'>断开</button><br />
    <button id='ToggleConnection' type="button" onclick='seestate();'>状态</button><br />
</body>
</html>

 

使用的浏览器版本:Google Chrome 21.0.1180.83m


但一直都没握手成功,发送了连接浏览器没任何反应,但管理服务器端确能触发onclose事件。

 

求解惑?

osEye的主页 osEye | 初学一级 | 园豆:137
提问于:2012-08-23 15:02
< >
分享
最佳答案
0
osEye | 初学一级 |园豆:137 | 2012-08-24 15:59
其他回答(4)
0

最后缺一个换行!

江大渔 | 园豆:267 (菜鸟二级) | 2012-08-31 16:52

不行的。最后是去掉最后一行,再加上一个换行才行。

支持(0) 反对(0) osEye | 园豆:137 (初学一级) | 2012-09-01 10:45

@osEye:

两个问题

1) Handshake结尾应该两个换行

2) 要传回和请求相匹配的protocol

支持(0) 反对(0) 江大渔 | 园豆:267 (菜鸟二级) | 2012-09-01 11:10
0

responseBuilder.Append("Sec-WebSocket-Protocol: chat" + Environment.NewLine + Environment.NewLine);

jesse_xie | 园豆:377 (菜鸟二级) | 2014-10-20 11:06
0

http://www.blue-zero.com/WebSocket/ 在线WebSocket测试,客户端完美兼容IE6及以上浏览器,服务端采用【C#.NET】异步socket开发,支持多客户同时在线。

阿煌 | 园豆:204 (菜鸟二级) | 2016-03-31 18:42
0

你注释掉的这两句:  //byte[] msg = Encoding.UTF8.GetBytes("hello");
            //state.workSocket.Send(msg);

改成下面的:

 byte[] msg = PackageServerData("hello from server");

state.workSocket.Send(msg);

 

private static 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;
        }

 

就可以握手成功了。

参考:https://blog.csdn.net/qq_20282263/article/details/54310737

 

橘子西瓜 | 园豆:213 (菜鸟二级) | 2018-05-24 14:27
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册