C# socket 实现消息中心向消息平台 转发消息 (修改)
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 实现消息中心向消息平台 转发消息 (修改)的更多相关文章
- C# socket 实现消息中心向消息平台 转发消息
公司用到,直接粘代码了 using System; using System.Collections.Generic; using System.Configuration; using System ...
- IBM MQ消息中间件jms消息中RHF2消息头的处理
公司的技术平台在和某券商对接IBM MQ消息中间件时,发送到MQ中的消息多出了消息头信息:RHF2,造成消息的接收处理不正常.在此记录此问题的处理方式. 在IBM MQ中提供了一个参数 targetC ...
- 如何在MFC DLL中向C#类发送消息
如何在MFC DLL中向C#类发送消息 一. 引言 由于Windows Message才是Windows平台的通用数据流通格式,故在跨语言传输数据时,Message是一个不错的选择,本文档将描述如何在 ...
- 微信开发——微信公众平台实现消息接收以及消息的处理(Java版)
本文主要讲述了如何在微信公众平台实现消息接收以及消息的处理,使用java语言开发,现在把实现思路和代码整理出来分先给兄弟们,希望给他们带来帮助. 温馨提示: 这篇文章是依赖前几篇的文章的. 第一篇:微 ...
- Team Foundation 中的错误和事件消息
Visual Studio Team System Team Foundation 中的错误和事件消息 Team Foundation 通过显示错误消息和事件消息来通知您操作成功以及操作失败.一部分错 ...
- ROS Learning-027 (提高篇-005 A Mobile Base-03) 控制移动平台 --- Twist 消息
ROS 提高篇 之 A Mobile Base-03 - 控制移动平台 - Twist 消息 我使用的虚拟机软件:VMware Workstation 11 使用的Ubuntu系统:Ubuntu 14 ...
- Delphi中SendMessage使用说明(所有消息说明) good
Delphi中SendMessage使用说明 SendMessage基础知识 函数功能:该函数将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回.而函数Po ...
- vivo鲁班RocketMQ平台的消息灰度方案
一.方案背景 RocketMQ(以下简称MQ)作为消息中间件在事务管理,异步解耦,削峰填谷,数据同步等应用场景中有着广泛使用.当业务系统进行灰度发布时,Dubbo与HTTP的调用可以基于业界通用的灰度 ...
- ASP.NET MVC5+EF6+EasyUI 后台管理系统(73)-微信公众平台开发-消息管理
系列目录 前言 回顾上一节,我们熟悉的了解了消息的请求和响应,这一节我们来建立数据库的表,表的设计蛮复杂 你也可以按自己所分析的情形结构来建表 必须非常熟悉表的结果才能运用这张表,这表表的情形涵盖比较 ...
随机推荐
- IIS报错 未将对象引用设置到对象的实例。
在vs中运行正常的项目 ,发布到IIS总是提示 未将对象引用设置到对象的实例. 运行静态页面 html正常,只是打开.aspx页面的时候报错,在确保了数据库,配置,权限均正常的情况下. 错误原因:先安 ...
- 打地鼠游戏ios源码
打地鼠游戏源码,游戏是一款多关卡基于cocos2d的iPad打地鼠游戏源码,这也是一款高质量的打地鼠游戏源码,可以拥有逐步上升的关卡的设置,大家可以在关卡时设置一些商业化的模式来盈利的,非常完美的一款 ...
- MySql安装方法和配置、解决中文乱码
MySql Server安装步骤 1安装MySql Server 2 安装MySqlServer管理工具 解压中文语言包,将文件复制到安装目录下覆盖 文件覆盖后,打开软件设置语言为中文(CN) 3 M ...
- vim插件之SnipMate
SnipMate简介 snipMate一款功能强大的代码补齐插件,可自定义代码模板,并具备单词补齐的功能. vim插件snipMate下载地址 SnipMate安装 将snipMate.zip解压到~ ...
- Memento
#include <iostream> #include <string> using namespace std; class Memento { public: Memen ...
- 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 ...
- 神奇的fastcgi_finish_request
当PHP运行在FastCGI模式时,PHP FPM提供了一个名为fastcgi_finish_request的方法.按照文档上的说法,此方法可以提高请求的处理速度,如果有些处理可以在页面生成完后再进行 ...
- 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 …… ...
- CentOS下MySQL忘记root密码解决方法【转载】
1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态下,其他的用户也可以任意地登录 ...
- MySQL远程访问授权
开启 MySQL 的远程登陆帐号有两大步: 1.确定服务器上的防火墙没有阻止 3306 端口. MySQL 默认的端口是 3306 ,需要确定防火墙没有阻止 3306 端口,否则远程是无法通过 330 ...