Socket 和 SignalR WS WSS

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");
        }
    }
}

*
*
*
*
*

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值