Socket 和 SignalR WS WSS

news/2024/7/5 19:27:46

HTML5 WebSocket 
ASP.NET Core 中的 WebSocket 支持

WS: WebSocket
WSS: WebSocket Secure
WS是非安全的,WSS是安全的。非安全的没有证书,安全的需要SSL证书。
WS的体现形式是TCP + WS AS WS ,WSS的体现形式是TCP + TLS + WS AS WSS。
WS一般默认是80端口,而WSS默认是443端口,大多数网站用的就是80和433端口。
http协议下使用ws,https协议下使用wss。
webSocket = new WebSocket("ws://localhost:port/hub");
webSocket = new WebSocket("wss://localhost:port/hub");

一、WebSocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议
支持双向通信,实时性更强
可以发送文本,也可以发送二进制数据
减少通信量:只要建立起WebSocket连接,就希望一直保持连接状态。和HTTP相比,不但每次连接时的总开销减少,而且由于WebSocket的首部信息很小,通信量也相应减少了

二、双向通信
HTTP 协议有一个缺陷:通信只能由客户端发起。举例来说,我们想了解今天的天气,只能是客户端向服务器发出请求,服务器返回查询结果。HTTP 协议做不到服务器主动向客户端推送信息。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。
在WebSocket协议之前,有三种双向通信的方式:轮询(polling)、长轮询(long-polling)和iframe流(streaming)。
1、轮询(polling)
轮询是客户端和服务器之间会一直进行连接,每隔一段时间就询问一次。其缺点也很明显:连接数会很多,一个接受,一个发送。而且每次发送请求都会有Http的Header,会很耗流量,也会消耗CPU的利用率。
优点:实现简单,无需做过多的更改
缺点:轮询的间隔过长,会导致用户不能及时接收到更新的数据;轮询的间隔过短,会导致查询请求过多,增加服务器端的负担
2、长轮询(long-polling)
长轮询是对轮询的改进版,客户端发送HTTP给服务器之后,看有没有新消息,如果没有新消息,就一直等待。当有新消息的时候,才会返回给客户端
优点:比 Polling 做了优化,有较好的时效性
缺点:保持连接会消耗资源; 服务器没有返回有效数据,程序超时。
3、iframe流(streaming)
iframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长连接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。
优点:消息能够实时到达;浏览器兼容好
缺点:服务器维护一个长连接会增加开销;IE、chrome、Firefox会显示加载没有完成,图标会不停旋转。

三、Socket
Socket 是一个网络通信的套接字(接口);分为 服务端 和 客户端;使用 TCP/IP协议 或 UDP 协议;

服务端

private void Start_Click(object sender, EventArgs e)
{
    try
    {
        var _ip = txtIP.Text;
        var _port = txtPort.Text;
        Validate(_ip, _port);

        socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        IPAddress ip = IPAddress.Parse(_ip);
        //将IP地址和端口号绑定到网络节点endpoint上 
        //IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(_port));
        IPEndPoint point = new IPEndPoint(IPAddress.Any, Convert.ToInt32(_port));//自动获取ip可使用此方法

        socketWatch.Bind(point);
        ShowMsg("开始监听 Ln 60...");
        LogUtils.GetInstance().Info("Ln 61...");

        //设置监听 - 将套接字的监听队列长度限制为10
        socketWatch.Listen(10);
        ShowMsg("开始监听 Ln 65...");
        LogUtils.GetInstance().Info("Ln 66...");

        Thread thread = new Thread(Listen);
        thread.IsBackground = true;
        thread.Start();
        Start.Enabled = false;
        btnStop.Enabled = true;

        ShowMsg("开始监听客户端传来的信息 Ln 82...");
    }
    catch (Exception ex)
    {
        MessageBox.Show("启动服务失败,请联系管理员!");
        LogUtils.GetInstance().Error(ex.Message);
    }
}

客户端

using CoreLibrary;
using CoreLibrary.UMeeting;
using Lawyer.Api.RequestModel;
using Lawyer.Entity;
using Newtonsoft.Json;
using System;
using System.Configuration;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Web.Mvc;

namespace Lawyer.Api.Controllers
{
    public class DefaultController : Controller
    {
        log4net.ILog logger = log4net.LogManager.GetLogger(typeof(ConferenceController));

        string ClassName = string.Empty;
        string MaxCallTime = string.Empty;

        ManualResetEvent connectDone = new ManualResetEvent(false);
        ManualResetEvent sendDone = new ManualResetEvent(false);
        ManualResetEvent receiveDone = new ManualResetEvent(false);
        String response = String.Empty;
        Socket tcpClient = null;

        public DefaultController()
        {
            ClassName = "Api.Controllers.ConferenceController";
            MaxCallTime = StringPlus.GetWebConfigKey("UMMaxCallTime");

            IPAddress ipaddress = IPAddress.Parse("101.201.44.11");
            EndPoint point = new IPEndPoint(ipaddress, 8803);
            tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            tcpClient.BeginConnect(point, new AsyncCallback(ConnectCallback), tcpClient);//建立连接  
            connectDone.WaitOne();

            string sendMsg = "{\"key\":\"verify\",\"command\":9,\"userid\":\"8888888\",\"password\":\"8888888888\"}";
            Send(tcpClient, sendMsg, 9);
            sendDone.WaitOne();
        }

        /// <summary>
        /// 双向回呼
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult CallBack(string conferenceid)
        {
            try
            {
                Thread thread = new Thread(new ParameterizedThreadStart(Monitor));
                thread.IsBackground = true;
                thread.Start(conferenceid);
                return ResultJsonMessage.Tool.SuccessResult();
            }
            catch (Exception ex)
            {
                logger.Info("Entered CallBack() " + ex.Message);
                return ResultJsonMessage.Tool.ExceptionResult(ex);
            }
        }

        /// <summary>
        /// 修改订单状态
        /// </summary>
        void UpdateOrder(object conferenceid)
        {
            try
            {
                logger.Info("Entered UpdateOrder 开始订单修改操作");
                OrderCallback o = biz.GetModelByCallSid(conferenceid.ToString());
                if (o != null)
                {
                    logger.Info("Entered UpdateOrder 执行业务逻辑");
                }
            }
            catch (Exception ex)
            {
                logger.Info("Entered UpdateOrder(" + conferenceid.ToString() + ") " + ex.Message);
            }
        }

        /// <summary>
        /// 监听会议
        /// </summary>
        /// <param name="conferenceid"></param>
        void Monitor(object conferenceid)
        {
            string monitor = "{\"key\":\"" + conferenceid + "\",\"command\":13,\"regphoneid\":\"" + ConfigurationManager.AppSettings["UMregphoneid"] + "\",\"conferenceid\":\"" + conferenceid + "\"}";
            Send(tcpClient, monitor, 13);
            sendDone.WaitOne();
            Receive(tcpClient);
            receiveDone.WaitOne();
        }

        private void ConnectCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.     
                Socket client = (Socket)ar.AsyncState;
                // Complete the connection.     
                client.EndConnect(ar);
                ///Console.WriteLine("Socket connected to {0}", client.RemoteEndPoint.ToString());
                logger.Info(string.Format("Socket connected to {0}", client.RemoteEndPoint.ToString()));
                // Signal that the connection has been made.     
                connectDone.Set();
            }
            catch (Exception e)
            {
                //Console.WriteLine(e.ToString());
                logger.Info("ConnectCallback Exception Ln 304" + e.ToString());
            }
        }

        private void Send(Socket client, String data, int type)
        {
            // Convert the string data to byte data using ASCII encoding.     
            byte[] byteData = Encoding.UTF8.GetBytes(data);

            #region

            byte[] abuff = new byte[4];
            byte[] bbuff = new byte[1];

            ConvertIntToByteArray(data.Length + abuff.Length + bbuff.Length, ref abuff);
            ConvertIntToByte(type, ref bbuff);

            byte[] d = new byte[2048];
            abuff.CopyTo(d, 0);
            bbuff.CopyTo(d, abuff.Length);
            byteData.CopyTo(d, abuff.Length + bbuff.Length);

            int dlength = byteData.Length + 5;

            #endregion            
            client.BeginSend(d, 0, dlength, 0, new AsyncCallback(SendCallback), client);
        }

        private void SendCallback(IAsyncResult ar)
        {
            try
            {
                // Retrieve the socket from the state object.     
                Socket client = (Socket)ar.AsyncState;
                // Complete sending the data to the remote device.     
                int bytesSent = client.EndSend(ar);
                //Console.WriteLine("Sent {0} bytes to server.", bytesSent);
                logger.Info("SendCallback " + string.Format("Sent {0} bytes to server.", bytesSent));
                // Signal that all bytes have been sent.     
                sendDone.Set();
            }
            catch (Exception e)
            {
                logger.Info("SendCallback Exception Ln 347 " + e.ToString());
            }
        }

        private void Receive(Socket client)
        {
            try
            {
                // Create the state object.     
                StateObject state = new StateObject();
                state.workSocket = client;
                // Begin receiving the data from the remote device.     
                client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
            }
            catch (Exception e)
            {
                //Console.WriteLine(e.ToString());
                logger.Info("Receive Exception Ln 364 " + e.ToString());
            }
        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            //logger.Info("Entered ReceiveCallback Begin Ln 370");
            try
            {
                // Retrieve the state object and the client socket     
                // from the asynchronous state object.     
                StateObject state = (StateObject)ar.AsyncState;
                Socket client = state.workSocket;
                // Read data from the remote device.     
                int bytesRead = client.EndReceive(ar);
                if (bytesRead > 0)
                {
                    // There might be more data, so store the data received so far.
                    state.sb.Append(Encoding.UTF8.GetString(state.buffer, 0, bytesRead));

                    //int headerLen = BitConverter.ToInt32(state.buffer.Take(4).ToArray(), 0);
                    //logger.Info("Entered header长度 " + headerLen);

                    string log = "";
                    if (bytesRead > 5)
                    {
                        log = Encoding.UTF8.GetString(state.buffer, 5, bytesRead);
                    }
                    else
                    {
                        log = Encoding.UTF8.GetString(state.buffer, 0, bytesRead);
                    }
                    if (bytesRead > 50)
                    {
                        ConvertObj(log);
                    }
                    //log = log.Substring(0, log.LastIndexOf("}") + 1);
                    //logger.Info("Entered Ln 400 " + log);
                    // Get the rest of the data.     
                    client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReceiveCallback), state);
                }
                else
                {
                    // All the data has arrived; put it in response.     
                    if (state.sb.Length > 1)
                    {
                        response = state.sb.ToString();
                        logger.Info("Entered response Ln 410 " + response);
                    }
                    // Signal that all bytes have been received. 
                    receiveDone.Set();
                }
                //logger.Info("Entered state.sb Ln 415 " + state.sb.ToString());
            }
            catch (Exception e)
            {
                //Console.WriteLine(e.ToString());
                logger.Info("ReceiveCallback Exception Ln 420 " + e.ToString());
            }
            //logger.Info("Entered ReceiveCallback End Ln 422");
        }

        bool ConvertIntToByteArray(Int32 m, ref byte[] arry)
        {
            if (arry == null) return false;
            if (arry.Length < 4) return false;

            arry[0] = (byte)(m & 0xFF);
            arry[1] = (byte)((m & 0xFF00) >> 8);
            arry[2] = (byte)((m & 0xFF0000) >> 16);
            arry[3] = (byte)((m >> 24) & 0xFF);

            return true;
        }

        bool ConvertIntToByte(Int32 m, ref byte[] arry)
        {
            if (arry == null) return false;
            arry[0] = (byte)(m & 0xFF);
            return true;
        }

        void ConvertObj(string log)
        {
            logger.Info("Entered ConvertObj Begin");
            logger.Info("Entered 原始字符串 " + log);
            try
            {
                string first = log.Substring(0, 1);
                string last = log.Substring(log.Length - 1, 1);

                if (first == "{" && last != "}")
                {
                    logger.Info("Entered 字符串截取操作 Ln 457 " + log);
                    log = log.Substring(0, log.LastIndexOf("}") + 1);
                }
                UMPushInfo umPush = (UMPushInfo)JsonConvert.DeserializeObject(log, typeof(UMPushInfo));
                if (umPush.command == 15 && umPush.phonelist != null)
                {
                    logger.Info("Entered phonelist总数:" + umPush.phonelist.Count.ToString());
                    if (umPush.phonelist[0].callstate == 2 || umPush.phonelist[0].callstate == 3)
                    {
                        //logger.Info("Entered 15 " + umPush.phonelist[0].callstate);
                        //logger.Info("Entered 结束会议");
                        //string command = "{\"key\":\"\",\"command\":12,\"client\":\"\",\"conferenceid\":\"" + umPush.conferenceid + "\",\"commandno \":9,\"memberid\":0,\"address\":\"\",\"phone\":\"\"}";
                        //Send(tcpClient, command, 12);
                    }
                }
                if (umPush.command == 15 && umPush.phonelist[0].callstate == 0)
                {
                    logger.Info("Entered 15 0 呼叫中");
                }
                if (umPush.command == 15 && umPush.phonelist[0].callstate == 1 && umPush.phonelist[0].role == 0)
                {
                    logger.Info("Entered 15 1 主持人接通");
                }
                if (umPush.command == 15 && umPush.phonelist[0].callstate == 1 && umPush.phonelist[0].role == 3)
                {
                    logger.Info("Entered 15 1 参会人接通");
                    Thread thread = new Thread(new ParameterizedThreadStart(UpdateOrder));
                    thread.IsBackground = true;
                    thread.Start(umPush.conferenceid);
                }
                if (umPush.command == 15 && umPush.phonelist[0].callstate == 2)
                {
                    logger.Info("Entered 15 2 未接通");
                }
                if (umPush.command == 15 && umPush.phonelist[0].callstate == 3)
                {
                    logger.Info("Entered 15 3 挂断");
                }
                if (umPush.command == 18 && umPush.conferencestate == 0)
                {
                    logger.Info("Entered 18 0 会议还未开始");
                }
                if (umPush.command == 18 && umPush.conferencestate == 1)
                {
                    logger.Info("Entered 18 1 会议正在召开");
                }
                if (umPush.command == 18 && umPush.conferencestate == 2)
                {
                    logger.Info("Entered 18 2 会议成功关闭");
                }
            }
            catch (Exception ex)
            {
                logger.Info("Entered Exception Ln 504 " + ex.Message);
                logger.Info("Entered " + log);
            }
            logger.Info("Entered ConvertObj End");
        }
    }
}

*
*
*
*
*


http://www.niftyadmin.cn/n/1995600.html

相关文章

Python中tuple类型的参数只有一个元素时,要加逗号

比如说传入的参数是这样的&#xff08;12&#xff09;&#xff0c;那Python解释器就会把这个参数当成是数字&#xff0c;必须加上逗号才行&#xff0c;即&#xff08;12&#xff0c;&#xff09;Python解释器才会把这个参数当成是元组类型的。

使用WinSock2 SPI进行网络控制访问内容

使用WinSock2 SPI进行网络控制访问内容 baidubaidu编者按&#xff1a;与传统的包过滤防火墙技术不同&#xff0c;本文从应用层网关技术入手&#xff0c;深入探讨了利用WinSock2 SPI进行网络内容访问控制的问题。这是网络安全的一项新内容&#xff0c;或者说&#xff0c;它为网络…

Tapestry的数据校验功能

Tapestry的数据校验功能 数据校验是Web应用的一个很重要的功能。tapestry支持配置式的数据校验&#xff0c;通过使用Delegate、FieldLabel和TextField对数据的显示进行修饰。在page文件中对各输入数据的校验规则进行配置。可以使用系统提供的Validator。出错信息也提供了多种…

HashMap源码解析(jdk1.7)

HashMap源码解析初始化信息添加元素删除元素查找元素containsKey&#xff1a;指定的key是否在HashMap中containsValue&#xff1a;查找HashMap中是否有指定的valueisEmptyindexFor&#xff1a;返回h在table数组中的位置写在后面初始化信息 //HashMap的初始容量&#xff0c;必须…

ZwQueryInformationFile 函数

ZwQueryInformationFile 函数The ZwQueryInformationFile routine returns various kinds of information about a given file object. NTSTATUS ZwQueryInformationFile( IN HANDLE FileHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, OUT PVOID FileInformatio…

Tapestry在静态页面和动态内容分工方面的研究

Tapestry在静态页面和动态内容分工方面的研究 Tapestry的一个最耀眼的功能是其绝好的模板设计思想&#xff0c;它能够将动态内容以极少的侵入性而展现到HTML页面上&#xff0c;我对其这一功能非常赞赏&#xff0c;如果 Tapestry能够像Spring那样把这一部分HTML模板解析功能独立…

java树形菜单制作

java树形菜单制作用到的技术代码实现用到的技术 SpringMVCSpringmybatiseasyui 代码实现 dto&#xff08;适用于easyui的实体类&#xff09; package com.grand.orgn.dto;import java.util.HashMap; import java.util.Map;/*** * author * 适用于easyUI树形结构的实体类* d…

文件-进程关联演示程序(出自CVC)

文件-进程关联演示程序(出自CVC)1、首先使用ZwQuerySystemInformation查询所有进程句柄&#xff0c;2、获取句柄所代表对象信息&#xff0c;查出目标文件。核心态程序相对简单&#xff0c;对于用户态程序&#xff0c;使用ZwQueryInformationFile同时与GetFileInformationByHand…