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)-微信公众平台开发-消息管理
系列目录 前言 回顾上一节,我们熟悉的了解了消息的请求和响应,这一节我们来建立数据库的表,表的设计蛮复杂 你也可以按自己所分析的情形结构来建表 必须非常熟悉表的结果才能运用这张表,这表表的情形涵盖比较 ...
随机推荐
- 在Web中实现C/S模式的Tab
在探讨C/S模式的Tab之前,我们先总结一下B/S模式的Tab通常是什么样的.web中常见的tab设计通常是用于分节展示大量信息以提高页面空间的利用率,而且这些信息通常是静态的,或者交互比较简单.通过 ...
- __main__:1: Warning: Unknown table 'employ' 0L
__main__:1: Warning: Unknown table 'employ' 0L from warnings import filterwarnings import MySQLdb fi ...
- Arch Linux 安装记录
Arch Linux 安装记录 基本上参考wiki上的新手指南,使用arch 2014.6.1 iso安装 设置网络 有线网络 Arch Linux 默认开启DHCP. 静态ip 首先关闭DHCP:s ...
- angular.extend(dst, src)对象拓展
angular.extend(dst, src) 作用:对象的拓展 参数: dst:拓展的对象 src:源对象 返回值:拓展的对象 var dst = {name: 'xxx', country: ...
- hadoop-集群管理(1)——配置文件
1. 配置文件列表如下: [tianyc@Route conf]$ pwd/home/tianyc/hadoop-1.0.4/conf[tianyc@Route conf]$ ll总用量 76-rw- ...
- 地球坐标系与投影方式的理解(关于北京54,西安80,WGS84;高斯,兰勃特,墨卡托投影)
一.地球模型 地球是一个近似椭球体,测绘时用椭球模型逼近,这个模型叫做参考椭球,如下图: 赤道是一个半径为a的近似圆,任一圈经线是一个半径为b的近似圆.a称为椭球的长轴半径,b称为椭球的短轴半径. a ...
- repeater标签双重循环的使用
在网站开发中,.NET中的repeater标签几乎是笔者首选,也是唯一一个不会生成多余元素的标签,所有样式都是自定义的,这点类似 struts中的<s:iterator/>标签. 在日常编 ...
- 使用HTML5构建下一代的Web Form
HTML语言作为如今编程最为广泛的语言,具有易用.快捷.多浏览平台兼容等特点,但是随着时代的进步,HTML的标准却停滞不前,这一次还在不断开发中的[color=#444444 !important]H ...
- java 求第n小的质数
package a小米; import java.util.Scanner; public class prime { public static boolean isPrime(int n){ fo ...
- iConvert Icons 图标转换生成利器,支持Windows, Mac OS X, Linux, iOS,和Android等系统
这是一款在线图标转换工具,生成的图标支持Windows, Mac OS X, Linux, iOS, 和 Android等主流系统. 可以上传图标文件转化成另一个平台下的图标文件,例如将windows ...