zoukankan      html  css  js  c++  java
  • 基于.NET 的WebSocket 的简单实例 建立连接

    HTML5新特性中,最令我激动的就是WebSocket,当时学习Silverlight的原因中,这也是很重要的一条。以前初步看了一下基本的原理,感觉也挺容易实现,这两天抽了个空,尝试着写了一下,还是碰到了几个问题,现在把基本的情况总结一下,以备自己将来或有兴趣的朋友查阅。
    我的机器环境:
    Windows 7 / Visual Studio 2010 SP1  C#/ 谷歌Chrome浏览器
    关于WebSocket原理的文章,大家可以在网上找找,非常多,但让人琢磨不透的也不少,这几个是我认为对我有帮助的几篇,也留下来,供各位查看,并在此对作者表示感谢:

    http://blog.csdn.net/fenglibing/article/details/6852497

    http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10 

    初步总结一下流程:
    客户端发起连接请求,向服务器发送如同下面格式的信息:
     
    GET / HTTP/1.1
    Upgrade: websocket
    Connection: Upgrade
    Host: 192.168.1.36:8050
    Sec-WebSocket-Origin: http://localhost:5113
    Sec-WebSocket-Key: YZgRBqBF5a5uWll/N8/R+Q==
    Sec-WebSocket-Version: 8
     
    服务端收到后,返回如同下面格式的信息:
     
    HTTP/1.1 101 Web Socket Protocol Handshake
    Upgrade: websocket
    Connection: Upgrade
    Sec-WebSocket-Accept: EailQ5Var3+aJmxVsqnNoxUc3sU=
    WebSocket-Origin: http://localhost:5113
    WebSocket-Location: ws://192.168.1.36:8050
     
    服务器端将客户发送的Sec-WebSocket-Key(YZgRBqBF5a5uWll/N8/R+Q==),经过一定的计算,得出一个Sec-WebSocket-Accept(EailQ5Var3+aJmxVsqnNoxUc3sU=),返回给客户,这其实就是一个握手的过程,一旦认证通过,即建立了真正的Socket连接,就可以正常的传送数据了。
    了解了这个过程,要开发服务端就相对容易了,对于这个版本中Accept的算法,可能是刚接触的人最不想去看,但又必须有的过程,还好我在网上找到了,并为此开发了一个专门的握手类,简化使用。
    代码如下:

      

    public class Handshake
    {        

        //用于保存请求串的键值对
        private Hashtable KeyValues;

        /// <summary>
        
    /// 构造函数
        
    /// </summary>
        
    /// <param name="request">请求串</param>
        public Handshake(string request)
        {
            //初始化哈希表
            KeyValues=new Hashtable();
                
            //分割字符串,用于分割每一行
            string[] separator1 = {"\r\n"};
            string[] rows = request.Split(separator1, StringSplitOptions.RemoveEmptyEntries);
            foreach (string row in rows)
            {
                //':'在每一行的第一个匹配项索引
                int splitIndex = row.IndexOf(':');
                if (splitIndex > 0
                {
                    //是键值对,保存到哈希表
                    string key1 = row.Substring(0, splitIndex).Trim(); //
                    string value1 = row.Substring(splitIndex + 1).Trim();  //
                    KeyValues.Add(key1, value1);  //保存到哈希表KeyValues
                }
            }
        }

        /// <summary>
        
    /// 返回的验证码
        
    /// </summary>
        public string KeyAccept
        {
            get 
            {
                string secWebSocketKey = GetValue("Sec-WebSocket-Key");
                string m_Magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
                return Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.ASCII.GetBytes(secWebSocketKey + m_Magic))); 
            }
        }

        /// <summary>
        
    /// 根据键获取对应值
        
    /// </summary>
        
    /// <param name="key"></param>
        
    /// <returns></returns>
        public string GetValue(string key)
        {
            //在哈希表中查询是否存在对应的键值
            if(KeyValues.ContainsKey(key))
                return KeyValues[key].ToString();
            else
                return string.Empty; //没有匹配的键值
        }
     
        /// <summary>
        
    /// 响应串
        
    /// </summary>
        public string Response
        {
            get 
            {
                StringBuilder response = new StringBuilder(); //响应串
                response.Append("HTTP/1.1 101 Web Socket Protocol Handshake\r\n");

                //将请求串的键值转换为对应的响应串的键值并添加到响应串
                response.AppendFormat("Upgrade: {0}\r\n", GetValue("Upgrade"));
                response.AppendFormat("Connection: {0}\r\n", GetValue("Connection"));
                response.AppendFormat("Sec-WebSocket-Accept: {0}\r\n", KeyAccept);
                response.AppendFormat("WebSocket-Origin: {0}\r\n", GetValue("Sec-WebSocket-Origin"));
                response.AppendFormat("WebSocket-Location: {0}\r\n", GetValue("Host"));

                response.Append("\r\n");

                return response.ToString(); 
            }
        }
    }


    客户端的关键代码:
    function connect() 
    {
        try 
        {
            var readyStatus = new Array("正在连接", "已建立连接", "正在关闭连接", "已关闭连接");
            var host = "ws://192.168.1.36:8050";
            conn = new WebSocket(host);
            var message = document.getElementById("message");
            message.innerHTML += "<p>Socket 状态:" + readyStatus[conn.readyState] + "</p>";
            conn.onopen = function () 
            {
                message.innerHTML += "<p>Socket状态:" + readyStatus[conn.readyState] + "</p>";
            }

            conn.onmessage = function (msg) {
                        message.innerHTML += "<p>接收消息:" + msg.data + "</p>";
                    }

            conn.onclose = function (event) {
                        message.innerHTML += "<p>Socket状态:" + readyStatus[conn.readyState] + "</p>";
                    }

         }
         catch (exception) {
                    message.innerHTML += "<p>有错误发生.</p>";
         }
    }
    这样,大家可以试试,一个基于原生Socket支持的Web应用就迈出了他的第一步了。
     
    下一步,我会实现一个能进行简单沟通的聊天室。
     
  • 相关阅读:
    Linux下配置APUE的编译 报错之后如何处理
    Sed命令的使用详细解释
    Linux下安装xrdp
    CentOS7.1 VNC Server服务配置
    Linux下core文件调试方法
    GDB获取帮助信息
    gdb调试工具学习
    Linux中tftp安装及使用笔记
    CentOS7.3安装Python3.6
    C#语言注释详解
  • 原文地址:https://www.cnblogs.com/xiaoyaoguzhu/p/2288349.html
Copyright © 2011-2022 走看看