using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Jinher.AMP.SNS.Chat.Client;
using Jinher.AMP.SNS.Chat.Deploy.CustomDTO;
using Jinher.AMP.SNS.Chat.Packet;
using Jinher.AMP.SNS.Chat.Utility;

namespace Jinher.AMP.SNS.Chat.SocketManager
{
    /// <summary>
    /// 消息服务基类
    /// </summary>
    public abstract class MessageCenter
    {
        /// <summary>
        /// 表示是否连接上
        /// </summary>
        public bool IsConnected { get; protected set; }
        /// <summary>
        /// 表示是否进行第一次握手协议
        /// </summary>
        public bool IsHandStake { get; protected set; }
        /// <summary>
        /// 表示是否注册APP
        /// </summary>
        public bool IsRegisterApp { get; protected set; }
        private string _ip = string.Empty;
        ;
        private object lockObject = new object();

        List<byte[]> byteList = new List<byte[]>();
        //通知

        private SocketAsyncEventArgsPool pool = null;
        private BufferManager m_bufferManager = null;
        /// <summary>
        /// 线程休眠时间(毫秒)
        /// </summary>
        ;
        //连接对象
        private Socket _socket = null;

        ;

        protected Action<List<MessageTemplate>> MyAction = null;
        protected Action<WebMessageDTO> receiveAction = null;
        public MessageCenter()
        {
            //初始化,获取Host和Port
            _ip = System.Configuration.ConfigurationManager.AppSettings["serverip"];
            _port = int.Parse(System.Configuration.ConfigurationManager.AppSettings["port"]);
            maxNumber = ");
            ";
            threadSleepTime = int.Parse(timer);
            //初始化连接对象
            InitSocket();
        }
        /// <summary>
        /// 带委托的构造函数
        /// </summary>
        /// <param name="action"></param>
        public MessageCenter(Action<List<MessageTemplate>> action)
            : this()
        {
            MyAction = action;
        }

        /// <summary>
        /// 启动消息中心
        /// </summary>
        public void Run()
        {
            try
            {
                LogHelper.WriteLog("启动服务");
                //第一次连接服务器
                Connect();
                //开始接受
                AccpetTo();
                //开始处理接受的数据
                ProcessAccpet();
                //保持连接
                KeepConnect();
                //推送消息队列
                //SendAsync();

                Task.Factory.StartNew(new Action(() =>
                {
                    client = ChatClient.Instance(ConfigurationManager.AppSettings["notificationUri"]);

                    client.OnMsgReceiveed = null;
                    client.OnMsgReceiveed += client_OnMsgReceiveed;
                }));

            }
            catch (SocketException exception)
            {
                //socket出错
                LogHelper.WriteLog("socket创建连接出错,尝试重新启动", exception);
                Thread.Sleep();
                this.Run();
            }
            catch (Exception ex)
            {
                //未知错误
                LogHelper.WriteLog("启动时发生未知错误!", ex);
                throw;
            }
            finally
            {
                //重置连接
                //ResetConnect();
            }
        }

        #region 连接服务器

        /// <summary>
        /// 连接服务器
        /// </summary>
        protected void Connect()
        {
            try
            {
                if (_socket == null)
                {
                    InitSocket();
                }
                LogHelper.WriteLog("开始建立连接");
                _socket.Connect(IPAddress.Parse(_ip), _port);
                LogHelper.WriteLog("连接已经建立");
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog("出错了", ex);
                LogHelper.WriteLog("建立连接失败,等待重新建立连接");
                Thread.Sleep(threadSleepTime);
                Connect();
                return;
            }

            //先进行第一次握手协议
            HandShakeCmdOp();
            //注册app
            RegisterApp();

            IsConnected = true;
        }
        /// <summary>
        /// 先进行第一次握手协议
        /// </summary>
        private void HandShakeCmdOp()
        {
            if (!IsHandStake)
            {
                LogHelper.WriteLog("开始第一次握手");

                _socket.Send(pmsMessage.HandShakePacket());
                IsHandStake = true;
                LogHelper.WriteLog("成功握手");
            }

        }
        /// <summary>
        /// 注册app
        /// </summary>
        private void RegisterApp()
        {
            //            一级命令:XNS_ROUTER
            //二级命令:REGISTER_SOCIAL_APP
            //并且规定AppId:99999999
            LogHelper.WriteLog("开始注册APP");
            _socket.Send(pmsMessage.RegisterPacket());

            IsRegisterApp = true;
            LogHelper.WriteLog("注册成功");
        }

        /// <summary>
        /// 初始化连接对象
        /// </summary>
        private void InitSocket()
        {
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        }

        #endregion

        #region 发送消息

        /// <summary>
        /// 发送消息(异步)
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="count">表示失败重新发送次数</param>
        /// <returns></returns>
        )
        {
            //先将该消息尝试发送,如果发送失败,则连接后继续发送
            //byteList.Add(buffer);

            //启动任务,发送消息
            Task.Factory.StartNew(new Action(() =>
            {
                try
                {
                    if (_socket != null && IsConnected && _socket.Connected && !_isResetConnecting)
                    {
                        lock (lockObject)
                        {
                            if (_socket != null && IsConnected && _socket.Connected && !_isResetConnecting)
                            {
                                SendByInit(buffer);
                            }
                            else
                            {
                                ResetConnect();
                                SendAsync(buffer);
                            }
                        }

                    }
                    else
                    {
                        ResetConnect();
                        SendAsync(buffer);
                    }
                }
                catch (Exception)
                {
                    //重发一次
                    )
                    {
                        //表示失败重新发送
                        SendAsync(buffer, count + );
                    }
                    else
                    {
                        ResetConnect();
                        SendAsync(buffer);
                    }
                }
                finally
                {

                }

            }));

        }
        /// <summary>
        /// 发送数据()
        /// </summary>
        /// <param name="buffer"></param>
        private void SendByInit(byte[] buffer)
        {
            _socket.BeginSend(buffer, , buffer.Length, SocketFlags.None, new AsyncCallback(SendComplated), _socket);
        }

        /// <summary>
        /// 发送消息回调函数
        /// </summary>
        /// <param name="ar"></param>
        private void SendComplated(IAsyncResult async)
        {
            try
            {
                Socket skt = async.AsyncState as Socket;
                if (skt.Connected)
                {
                    skt.EndSend(async);
                }
                LogHelper.WriteLog("发送成功");
            }
            catch (SocketException ex)
            {
                //日志文件

            }
        }

        #endregion

        #region 接受消息(方式一)

        /// <summary>
        /// 接受消息方式一
        /// </summary>
        public void AccpetOne()
        {
            LogHelper.WriteLog("开始建立接受消息(方式一)");
            pool = );

            // 预先分配一个对象池
            SocketAsyncEventArgs readWriteEventArg;

            ; i < maxNumber; i++)
            {
                m_bufferManager =  * );
                m_bufferManager.InitBuffer();
                //初始化 SocketAsyncEventArgs
                readWriteEventArg = new SocketAsyncEventArgs();
                readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(Receive_Completed);
                readWriteEventArg.UserToken = new AsyncUserToken() { Manager = m_bufferManager };
                // 从缓冲池分配一个字节缓冲区SocketAsyncEventArg对象
                m_bufferManager.SetBuffer(readWriteEventArg);
                // add SocketAsyncEventArg to the pool
                pool.Push(readWriteEventArg);
            }
            //取出  监视
            Receive();

        }

        private void Receive()
        {
            if (IsConnected && IsRegisterApp && IsHandStake)
            {
                SocketAsyncEventArgs readEventArgs = null;
                readEventArgs = pool.Pop();
                if (readEventArgs != null)
                {
                    ((AsyncUserToken)readEventArgs.UserToken).Socket = _socket;

                    _socket.ReceiveAsync(readEventArgs);
                }
            }
        }

        private void Receive_Completed(object sender, SocketAsyncEventArgs e)
        {
            Receive();
            ReceiveAsync(e);
        }
        private void ReceiveAsync(SocketAsyncEventArgs e)
        {
            AsyncUserToken token = (AsyncUserToken)e.UserToken;
             && e.SocketError == SocketError.Success)
            {
                //echo the data received back to the client
                e.SetBuffer(, e.BytesTransferred);
                //string txt = Encoding.Default.GetString(e.Buffer, 0, e.BytesTransferred);
                //Console.WriteLine(tmp);
                //通知
                #region 收到消息平台发送来的消息
                //client.Send();
                )
                {
                    byte[] temp = new byte[e.BytesTransferred];
                    Array.Copy(e.Buffer, , temp, , e.BytesTransferred);

                    ProcessAccpet(temp, e.BytesTransferred);
                }
                #endregion

                BufferManager bufferManager = ((AsyncUserToken)(e.UserToken)).Manager;
                if (bufferManager == null)
                {
                    bufferManager =  * );
                    e.UserToken = new AsyncUserToken() { Manager = bufferManager };
                }
                bufferManager.FreeBuffer(e);
                bufferManager.SetBuffer(e);
                //回收
                pool.Push(e);

            }
        }

        #endregion

        #region 接受消息(方式二)
        List<byte> testList = new List<byte>();
        private void AccpetTo()
        {
            LogHelper.WriteLog("开始建立接受消息(方式二)");

            Task.Factory.StartNew(new Action(() =>
            {
                try
                {
                     * ];
                    while (true)
                    {
                        int r = _socket.Receive(bytes);
                        //通知
                        #region 收到消息平台发送来的消息
                        )
                        {
                            byte[] temp = new byte[r];
                            Array.Copy(bytes, , temp, , r);
                            lock ("我要给集合增加数据")
                            {
                                testList.AddRange(temp);
                            }
                            // ProcessAccpet(temp, r);
                        }
                        #endregion
                        Array.Clear(bytes, , r);
                    }
                }
                catch (SocketException ex)
                {
                    LogHelper.WriteLog("socket出错", ex);
                    ResetConnect();
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog("出错", ex);
                }

            }));
        }

        #endregion

        #region 收到的消息进行处理
        /// <summary>
        /// 消息处理中转
        /// </summary>
        /// <param name="p"></param>
        /// <param name="r"></param>
        private async void ProcessAccpet(byte[] p, int r)
        {
            //if (r > 10)
            //{
            //    LogHelper.WriteLog("收到正常消息");
            //    var result = pmsMessage.ReversePacketMessage(p, r);

            //    //发送给客户端
            //    ClientSend(result);

            //    //发送给测试端
            //    if (MyAction != null)
            //    {
            //        MyAction(result.ToList());
            //    }
            //}
            //else
            //{
            //    LogHelper.WriteLog(string.Format("收到心跳包"));
            //}

        }
        //标示处理任务是否正在运行
        private bool IsProcessAccpetRuning = false;
        private void ProcessAccpet()
        {
            if (IsProcessAccpetRuning)
            {//表示任务正在执行
                return;
            }
            else
            {
                IsProcessAccpetRuning = true;
            }
            Task.Factory.StartNew(new Action(() =>
            {
                //IsProcessAccpetRuning = false;
                //Thread.Sleep(100);
                //IsProcessAccpetRuning = true;
                while (IsProcessAccpetRuning)
                {
                    )
                    {
                        List<byte> tempList = new List<byte>();
                        lock ("我要给集合增加数据")
                        {
                            tempList = testList.ToList();
                            testList.Clear();
                        }
                        //启动一个任务来发送数据
                        Task.Factory.StartNew(new Action(() =>
                        {
                            var result = pmsMessage.ReversePacketMessage(tempList, tempList.Count);

                            //发送给客户端
                            ClientSend(result);

                            //发送给测试端
                            )
                            {
                                MyAction(result.ToList());
                            }
                        }));
                    }
                    else
                    {
                        Thread.Sleep();
                    }
                }
                LogHelper.WriteLog("新的处理请求,停止处理接受");
            }));
        }
        #endregion

        #region 保持连接

        /// <summary>
        /// 重置连接
        /// </summary>
        public void ResetConnect()
        {
            if (!_isResetConnecting)
            {
                lock (lockObject)
                {
                    if (!_isResetConnecting)
                    {
                        _isResetConnecting = true;
                        LogHelper.WriteLog("=========重新连接==============");
                        lock (lockObject)
                        {
                            this.Dispose();
                            InitSocket();
                        }
                        Thread.Sleep();
                        Run();
                        _isResetConnecting = false;
                    }
                }
            }

        }

        private Timer timer = null;
        /// <summary>
        /// 保持连接
        /// </summary>
        private void KeepConnect()
        {
            timer = new Timer(new TimerCallback((o) =>
            {
                if (IsConnected)
                {
                    //发送心跳包
                    SendAsync(pmsMessage.GetHeardbeat());
                    LogHelper.WriteLog("已经发送心跳包");
                }
            }), , , , ), , , , ));

        }

        #endregion

        #region 通知相关

        private ChatClient client = null;// ChatClient.Instance(ConfigurationManager.AppSettings["notificationUri"]);
        PacketConvert pmsMessage = new PacketConvert();
        private bool _isResetConnecting = false;

        /// <summary>
        /// 请求发送消息
        /// </summary>
        /// <param name="msg"></param>
        protected void client_OnMsgReceiveed(WebMessageDTO msg)
        {
            //请求发送消息
            LogHelper.WriteLog(string.Format("开始请求发送消息:消息id=>{0} **********消息内容=>:{1}", msg.MsgId, msg.Msg != null ? msg.Msg.Message : ""));
            byte[] bytes = pmsMessage.PacketMessage(msg);
            SendAsync(bytes);

            //发送给测试程序
            if (receiveAction != null)
            {
                receiveAction(msg);
            }
        }

        private void ClientSend(IList<MessageTemplate> message)
        {
            if (message != null && client != null)
                client.SendAsync(message);
        }
        #endregion

        #region 资源清理
        /// <summary>
        /// 清理资源
        /// </summary>
        public void Dispose()
        {
            IsRegisterApp = false;
            IsHandStake = false;
            IsConnected = false;
            if (_socket.Connected == true)
                _socket.Shutdown(SocketShutdown.Both);

            _socket.Dispose();
            _socket = null;
            pool = null;
            m_bufferManager = null;
        }

        #endregion

    }
}

C# socket 实现消息中心向消息平台 转发消息 (修改)的更多相关文章

  1. C# socket 实现消息中心向消息平台 转发消息

    公司用到,直接粘代码了 using System; using System.Collections.Generic; using System.Configuration; using System ...

  2. IBM MQ消息中间件jms消息中RHF2消息头的处理

    公司的技术平台在和某券商对接IBM MQ消息中间件时,发送到MQ中的消息多出了消息头信息:RHF2,造成消息的接收处理不正常.在此记录此问题的处理方式. 在IBM MQ中提供了一个参数 targetC ...

  3. 如何在MFC DLL中向C#类发送消息

    如何在MFC DLL中向C#类发送消息 一. 引言 由于Windows Message才是Windows平台的通用数据流通格式,故在跨语言传输数据时,Message是一个不错的选择,本文档将描述如何在 ...

  4. 微信开发——微信公众平台实现消息接收以及消息的处理(Java版)

    本文主要讲述了如何在微信公众平台实现消息接收以及消息的处理,使用java语言开发,现在把实现思路和代码整理出来分先给兄弟们,希望给他们带来帮助. 温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微 ...

  5. Team Foundation 中的错误和事件消息

    Visual Studio Team System Team Foundation 中的错误和事件消息 Team Foundation 通过显示错误消息和事件消息来通知您操作成功以及操作失败.一部分错 ...

  6. ROS Learning-027 (提高篇-005 A Mobile Base-03) 控制移动平台 --- Twist 消息

    ROS 提高篇 之 A Mobile Base-03 - 控制移动平台 - Twist 消息 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14 ...

  7. Delphi中SendMessage使用说明(所有消息说明) good

    Delphi中SendMessage使用说明 SendMessage基础知识 函数功能:该函数将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回.而函数Po ...

  8. vivo鲁班RocketMQ平台的消息灰度方案

    一.方案背景 RocketMQ(以下简称MQ)作为消息中间件在事务管理,异步解耦,削峰填谷,数据同步等应用场景中有着广泛使用.当业务系统进行灰度发布时,Dubbo与HTTP的调用可以基于业界通用的灰度 ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(73)-微信公众平台开发-消息管理

    系列目录 前言 回顾上一节,我们熟悉的了解了消息的请求和响应,这一节我们来建立数据库的表,表的设计蛮复杂 你也可以按自己所分析的情形结构来建表 必须非常熟悉表的结果才能运用这张表,这表表的情形涵盖比较 ...

随机推荐

  1. IIS报错 未将对象引用设置到对象的实例。

    在vs中运行正常的项目 ,发布到IIS总是提示 未将对象引用设置到对象的实例. 运行静态页面 html正常,只是打开.aspx页面的时候报错,在确保了数据库,配置,权限均正常的情况下. 错误原因:先安 ...

  2. 打地鼠游戏ios源码

    打地鼠游戏源码,游戏是一款多关卡基于cocos2d的iPad打地鼠游戏源码,这也是一款高质量的打地鼠游戏源码,可以拥有逐步上升的关卡的设置,大家可以在关卡时设置一些商业化的模式来盈利的,非常完美的一款 ...

  3. MySql安装方法和配置、解决中文乱码

    MySql Server安装步骤 1安装MySql Server 2 安装MySqlServer管理工具 解压中文语言包,将文件复制到安装目录下覆盖 文件覆盖后,打开软件设置语言为中文(CN) 3 M ...

  4. vim插件之SnipMate

    SnipMate简介 snipMate一款功能强大的代码补齐插件,可自定义代码模板,并具备单词补齐的功能. vim插件snipMate下载地址 SnipMate安装 将snipMate.zip解压到~ ...

  5. Memento

    #include <iostream> #include <string> using namespace std; class Memento { public: Memen ...

  6. Win 2003下IIS6+Mysql+php5.2  isapi搭建 升级php5.2到5.3测试 借助fastcgi实现

    Win 2003下IIS6+Mysql+php5.2  原环境isapi搭建 升级php5.2到5.3测试 借助fastcgi实现 操作如下 实验前准备:php-5.3.5-Win32-VC6-x86 ...

  7. 神奇的fastcgi_finish_request

    当PHP运行在FastCGI模式时,PHP FPM提供了一个名为fastcgi_finish_request的方法.按照文档上的说法,此方法可以提高请求的处理速度,如果有些处理可以在页面生成完后再进行 ...

  8. C++求斐波那契数

    题目内容:斐波那契数定义为:f(0)=0,f(1)=1,f(n)=f(n-1)+f(n-2)(n>1且n为整数) 如果写出菲氏数列,则应该是: 0 1 1 2 3 5 8 13 21 34 …… ...

  9. CentOS下MySQL忘记root密码解决方法【转载】

    1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以任意地登录 ...

  10. MySQL远程访问授权

    开启 MySQL 的远程登陆帐号有两大步: 1.确定服务器上的防火墙没有阻止 3306 端口. MySQL 默认的端口是 3306 ,需要确定防火墙没有阻止 3306 端口,否则远程是无法通过 330 ...