【C#】【Demo】消息队列RabbitMQ,和TCP监听Demo。

 

注意连接队列服务器时,参数必须和服务器配置一致

  private string queue;//队列名
        private bool durable;//持久化
        private bool exclusive;//独占
        private bool autoDelete;//自动删除

默认帐号guest不能远程。

默认访问队列端口是5672,后台网站端口默认是15672。

 

1、实现发送和接收,类RabbitMQServerT

using System;
using MQServer;
using RabbitMQ.Client;
using System.Text;
using System.Configuration;
using RabbitMQ.Client.Events;
using Newtonsoft.Json;

namespace MQServer
{
    /// <summary>
    /// RabbitMQ消息队列类
    /// </summary>
    public class RabbitMQServerT 
    {
        protected readonly Action<string, object> receive;//接收回调
        private object penetrate;//接收回调透传参数
        private string queue;//队列名
        private bool durable;//持久化
        private bool exclusive;//独占
        private bool autoDelete;//自动删除
        private bool isBeginInvoke;//接收后业务是否异步,异步的话消息可能在确认前被其他线程读走,造成重复读。//不异步就阻塞。//异步请独占

        //接收消息对象
        private IConnection connection;
        private IModel channel;

        public bool IsReceive;

        private ConnectionFactory factory;
        private RabbitMQServerT()
        {
        }

        /// <summary>
        /// 使用默认配置参数
        /// </summary>
        /// <param name="_receive">消费事件,空则不消费</param>
        /// <param name="_queue">消息路径最后一层名字,可用于区分业务</param>
        /// <param name="_penetrate">接收回调透传参数</param>
        public RabbitMQServerT(Action<string, object> _receive, string _queue = @"hello", object _penetrate = null)
        {
            queue = _queue;
            receive = _receive;
            penetrate = _penetrate;
            isBeginInvoke = false;

            durable = bool.Parse(ConfigurationManager.AppSettings["RabbitMQ_durable"].ToString());//
            exclusive = bool.Parse(ConfigurationManager.AppSettings["RabbitMQ_exclusive"].ToString());//
            autoDelete = bool.Parse(ConfigurationManager.AppSettings["RabbitMQ_autoDelete"].ToString());//

            factory = new ConnectionFactory();
            factory.HostName = ConfigurationManager.AppSettings["RabbitMQHostName"];//RabbitMQ服务器
            factory.UserName = ConfigurationManager.AppSettings["RabbitMQUserName"];//用户名
            factory.Password = ConfigurationManager.AppSettings["RabbitMQPassword"];//密码
            factory.Port = int.Parse(ConfigurationManager.AppSettings["RabbitMQPort"].ToString());//
            if (!string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings["RabbitMQVirtualHost"]))
            {
                factory.VirtualHost = ConfigurationManager.AppSettings["RabbitMQVirtualHost"];//
            }
        }

        /// <summary>
        /// 使用手动参数
        /// </summary>
        /// <param name="_receive">消费事件,空则不消费</param>
        /// <param name="_queue">消息路径最后一层名字,可用于区分业务</param>
        /// <param name="_penetrate">接收回调透传参数</param>
        /// <param name="factory">连接队列服务器</param>
        /// <param name="durable">持久化</param>
        /// <param name="exclusive">独占</param>
        /// <param name="autoDelete">自动删除</param>
        /// <param name="isBeginInvoke">接收是否异步//异步请独占,否则异常</param>
        public RabbitMQServerT(Action<string, object> _receive, string _queue, object _penetrate, ConnectionFactory factory
            ,bool durable,bool exclusive, bool autoDelete,bool isBeginInvoke)
        {
            queue = _queue;
            receive = _receive;
            penetrate = _penetrate;

            this.factory = factory;
            this.durable = durable;
            this.exclusive = exclusive;
            this.autoDelete = autoDelete;
            this.isBeginInvoke = isBeginInvoke;

            //异步请独占,不然会重复读
            if (isBeginInvoke == true && exclusive == false) 
            {
                throw new Exception("接收消息队列对象RabbitMQServerT参数isBeginInvoke=true异步执行接收业务,如果要异步执行业务,请独占该消息exclusive=true,否则会被其他线程重复读取。");
            }
        }

        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="message"></param>
        public void Send(string message)
        {
            //发送消息队列
            try
            {
                using (var connection = factory.CreateConnection())
                {
                    using (var channel = connection.CreateModel())
                    {
                        channel.QueueDeclare(queue, durable, exclusive, autoDelete, null);//创建一个消息队列
                        var body = Encoding.UTF8.GetBytes(message);
                        channel.BasicPublish("", queue, null, body); //开始传递
                        //TLogHelper.Info(message, "RabbitMQServerTSend");//发送的内容写进TXT
                    }
                }
            }
            catch (Exception ex)
            {
                TLogHelper.Error(ex.Message, "发送消息队列异常RabbitMQServerTSend:\n" + message);
            }
        }
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="message"></param>
        public void Send(RabbitMQMsgModel model)
        {
            //发送消息队列
            string message = JsonConvert.SerializeObject(model);
            Send(message);
        }

        /// <summary>
        /// 进行接收消息队列
        /// </summary>
        public void Receive()
        {
            if (receive == null)
            {
                return;
            }
            IsReceive = true;
            try
            {
                connection = factory.CreateConnection();
                channel = connection.CreateModel();
              
                channel.QueueDeclare(queue, durable, exclusive, autoDelete, null);
                channel.BasicQos(prefetchSize: 0, prefetchCount: 1, global: false);

                var consumer = new EventingBasicConsumer(channel);
                consumer.Received += (model, ea) =>
                {
                    try
                    {
                        var body = ea.Body.ToArray();
                        var message = Encoding.UTF8.GetString(body);

                        //接收后业务
                        if (isBeginInvoke)
                        {
                            receive?.BeginInvoke(message, penetrate,(e)=>{
                                //确认消息
                                channel.BasicAck(ea.DeliveryTag, false);
                            },null);
                        }
                        else 
                        {
                            receive?.Invoke(message, penetrate);
                            //确认消息
                            channel.BasicAck(ea.DeliveryTag, false);
                        }
                    }
                    catch (Exception ex)
                    {
                        TLogHelper.Error(ex.Message, "接收消息队列业务异常Received:"+queue);
                    }
                    finally
                    {
                        //再次生成接收
                        Receive();
                    }
                };
                channel.BasicConsume(queue, true, consumer);
            }
            catch (Exception ex)
            {
                TLogHelper.Error(ex.Message, "接收消息队列异常Receive");
            }
        }

        /// <summary>
        /// 取消接收
        /// </summary>
        public void EndReceive()
        {
            IsReceive=false;
            channel.Dispose();
            connection.Dispose();
        }
    }
}
View Code

 

消息格式RabbitMQMsgModel

namespace MQServer
{
    public class RabbitMQMsgModel
    {
        /// <summary>
        /// 业务名
        /// </summary>
        public string BLLName { get; set; }

        /// <summary>
        /// 业务数据
        /// </summary>
        public object Data { get; set; }
    }
}
View Code

 

2、BLL实现消息业务

BaseMQBLL

using System;

namespace MQServer
{
    /// <summary>
    /// 使用队列业务基类
    /// </summary>
    public abstract class BaseMQBLL : IDisposable
    {
        public bool IsReceive { get { return MQ.IsReceive; } }

        protected readonly RabbitMQServerT MQ;

        private BaseMQBLL(){ }

        protected BaseMQBLL(string queue,object _penetrate) 
        {
            
            MQ = new MQServer.RabbitMQServerT((string source, object o) => {
                try
                {
                    ReceiveBack(source, _penetrate);
                    ////test
                    //throw new Exception("测试消息异常");
                }
                catch (Exception)
                {
                    throw;
                }
            }, queue, _penetrate: null);
        }
        /// <summary>
        /// 开启接收
        /// </summary>
        public void Receive()
        {
            MQ.Receive();
        }

        /// <summary>
        /// 关闭接收
        /// </summary>
        public void EndReceive()
        {
            MQ.EndReceive();
        }

        /// <summary>
        /// 声明必须重写的接收回调
        /// </summary>
        /// <param name="source"></param>
        /// <param name="receiveO"></param>
        protected abstract void ReceiveBack(string source, object receiveO);

        public void Dispose() 
        {
            EndReceive();
        }
    }
}
View Code

 

MQTestHello: BaseMQBLL

using MQServer;
using Newtonsoft.Json;

namespace BLL
{
    public class MQTestHello : BaseMQBLL
    {
        public MQTestHello()
            : base("hello", null)
        {
        }

        /// <summary>
        /// 重写接收回调
        /// </summary>
        /// <param name="source"></param>
        /// <param name="receiveO"></param>
        protected override void ReceiveBack(string source, object receiveO)
        {
            //解析source,根据source中的BLLName方法名,执行不同业务
            RabbitMQMsgModel model = JsonConvert.DeserializeObject<RabbitMQMsgModel>(source);

            switch (model.BLLName)
            {
                case "Hello":
                    Hello(model.Data);
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// 发送Hello消息
        /// </summary>
        public void SendHello(string msg)
        {
            MQ.Send(new RabbitMQMsgModel() { BLLName = "Hello", Data = msg });
        }

        /// <summary>
        /// 接收到Hello消息回调
        /// </summary>
        /// <param name="data"></param>
        public void Hello(object data)
        {
            TLogHelper.Info(JsonConvert.SerializeObject(data), "读取消息在MQTestHello");
        }
    }
}
View Code

 

3、记录日志

TLogHelper

using Newtonsoft.Json;
using System;
using System.IO;
using System.Messaging;
using System.Text;

namespace MQServer.Log
{
    public class TLogHelper
    {
        public static object _lock = new object();
        public static void MQ(Message myMessage,  string detail = "") 
        {
            string msg = JsonConvert.SerializeObject(myMessage.Body);

            Write(msg, detail, "MessageQueue");
        }

        public static void Info(string msg, string detail = "")
        {
            Write(msg, detail, "Info");
        }
        public static void Info(object msg, string detail = "")
        {
            Write(JsonConvert.SerializeObject(msg), detail, "Info");
        }

        public static void Error(string msg, string detail = "")
        {
            Write(msg, detail, "Error");
        }

        private static void Write(string msg,string detail="", string title = "Info") 
        {
            DateTime now = DateTime.Now;
            string logPath = System.Configuration.ConfigurationManager.AppSettings["MQServerTLogPath"];

            if (!Directory.Exists(logPath))
            {
                Directory.CreateDirectory(logPath);
            }

            logPath += now.ToString("yyyyMMdd") + ".txt";
            lock (_lock)
            {
                FileStream fs = new FileStream(@logPath, FileMode.OpenOrCreate, FileAccess.Write);

                StreamWriter m_streamWriter = new StreamWriter(fs);

                m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);

                m_streamWriter.WriteLine();
                m_streamWriter.WriteLine(now.ToString("yyyyMMddHHmmssfff") + " " + title);
                if (!string.IsNullOrWhiteSpace(detail))
                {
                    m_streamWriter.WriteLine(detail);
                }

                m_streamWriter.WriteLine(msg);

                m_streamWriter.Flush();

                m_streamWriter.Close();

                fs.Close();
            }
            

        }

        public static string Read() 
        {
            string res = "";
            string logPath = System.Configuration.ConfigurationManager.AppSettings["MQServerTLogPath"];
            
            logPath += DateTime.Now.ToString("yyyyMMdd") + ".txt";
            lock (_lock)
            {
                StreamReader fs = new StreamReader(@logPath, Encoding.UTF8);
                res = fs.ReadToEnd();
                fs.Dispose();
            }
            return res;
        }
    }
}
View Code

 

4、Form窗体测试

 RabbitMQForm : Form

using BLL;
using Newtonsoft.Json;
using System;
using System.Windows.Forms;

namespace WinFormActiveMQ
{
    public partial class RabbitMQForm : Form
    {
        static MQTestHello hello;
        static TCPTestHello tcpHello;
        static TCPTestHello tcpHello2;
        private Label la_main;
        private Timer tim;
        private System.Threading.Thread thrListener;
        private System.Threading.Thread thrListener2;
        public RabbitMQForm()
        {
            InitializeComponent();

            la_main = new Label();
            la_main.Name = "la_main";
            la_main.Width = 282;
            la_main.TabIndex = 0;
            Controls.Add(la_main);

            tim = new Timer();
            tim.Interval = 1000;
            tim.Tick += CheckReceive;
            tim.Start();

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            textBox1.ScrollBars = ScrollBars.Vertical;
            la_main.Text = "RabbitMQ消息队列,点击开启接收。";
            TCPIp1.Text = "127.0.0.1";
            TCPPort1.Text = "90";
            TCPIp2.Text = "127.0.0.1";
            TCPPort2.Text = "91";

            hello = new MQTestHello(); 
        }

        /// <summary>
        /// 守护线程
        /// 检测接收线程是否还在,不在了重新接收
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckReceive(object sender, EventArgs e)
        {
            //测试Hello队列
            if (TestHello.Checked)
            {
                if (hello!=null && !hello.IsReceive)
                {
                    hello.Receive();
                }
            }

            if (TCPHello.Checked)
            {
                if (tcpHello != null && !tcpHello.IsListening)
                {
                    thrListener = tcpHello.ListenStart(ListenClientBack);
                }
            }
            
            if (TCPListen2.Checked)
            {
                if (tcpHello2 != null && !tcpHello2.IsListening)
                {
                    thrListener2 = tcpHello2.ListenStart(ListenClientBack);
                }
            }

        }

        /// <summary>
        /// 开启接收Hello队列,并发送一条测试消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TestHello_CheckedChanged(object sender, EventArgs e)
        {
            if (TestHello.Checked)
            {
                //开启接收
                if (!hello.IsReceive)
                {
                    hello.Receive();
                }

                //测试发送
                hello.SendHello("测试第一消息");
            }
            else
            {
                //关闭接收
                hello.EndReceive();
            }
        }

        /// <summary>
        /// 开启接收TCP请求,hello业务的
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TCPHello_CheckedChanged(object sender, EventArgs e)
        {
            //设置ip端口输入
            TCPIp1.Enabled = !TCPHello.Checked;
            TCPPort1.Enabled = !TCPHello.Checked;

            if (TCPHello.Checked)
            {
                int port = 0;
                try
                {
                    port = int.Parse(TCPPort1.Text);
                }
                catch (Exception)
                {
                    TCPHello.Checked = !TCPHello.Checked;
                    TCPIp1.Enabled = !TCPHello.Checked;
                    TCPPort1.Enabled = !TCPHello.Checked;
                    MessageBox.Show("请输入正确端口号");
                    return;
                }

                tcpHello = new TCPTestHello(TCPIp1.Text, port, "", port);
                ///开启监听
                thrListener = tcpHello.ListenStart(ListenClientBack);
            }
            else
            {
                //关闭监听
                tcpHello.CloseListen();
            }
        }

        /// <summary>
        /// 收到终端的TCP请求后回调显示
        /// </summary>
        private string ListenClientBack(object obj)
        {
            if (obj == null) 
            {
                //监听执行回调出错
                changeListenText("\r\n  监听执行回调出错");

                //用选择框改变事件关闭监听
                TCPHello_CheckedChanged(null,null);
                return "";
            }

            string res = JsonConvert.SerializeObject(obj);
            changeListenText("\r\n收到终端的请求在Form:" + res);
            return res;
        }

        //修改主线程文本框值
        private delegate void SetTextCallback(string sssext);
        /// <summary>
        /// 修改主线程文本框值
        /// </summary>
        /// <param name="text"></param>
        private void changeListenText(string text)
        {
            if (this.textBox1.InvokeRequired)   //InvokeRequired会比较调用线程ID和创建线程ID
            {   //如果它们不相同则返回true
                SetTextCallback sss = new SetTextCallback(changeListenText);//类似于重载,调用自己
                this.Invoke(sss, new object[] { text });
            }
            else
            {
                this.textBox1.Text = text + this.textBox1.Text;
            }
        }

        /// <summary>
        /// 测试发送TCP请求
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TestRequestTcp_Click(object sender, EventArgs e)
        {
            try
            {
                if (tcpHello == null) 
                {
                    MessageBox.Show("请先打开监听");
                    return;
                }
                tcpHello.SendHello("测试发送TCP请求:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 监听2
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TCPListen2_CheckedChanged(object sender, EventArgs e)
        {

            //设置ip端口输入
            TCPIp2.Enabled = !TCPListen2.Checked;
            TCPPort2.Enabled = !TCPListen2.Checked;

            if (TCPListen2.Checked)
            {
                int port = 0;
                try
                {
                    port = int.Parse(TCPPort2.Text);
                }
                catch (Exception)
                {
                    TCPListen2.Checked = !TCPListen2.Checked;
                    TCPIp2.Enabled = !TCPListen2.Checked;
                    TCPPort2.Enabled = !TCPListen2.Checked;
                    MessageBox.Show("请输入正确端口号");
                    return;
                }

                ///开启监听2 
                tcpHello2 = new TCPTestHello(TCPIp2.Text, port, "", port);
                thrListener2 = tcpHello2.ListenStart(ListenClientBack2);
                 
            }
            else
            {
                tcpHello2.CloseListen();
            }
        }

        /// <summary>
        /// 收到终端的TCP请求后回调显示2
        /// </summary>
        private string ListenClientBack2(object obj)
        {
            if (obj == null)
            {
                //监听执行回调出错
                changeListenText("\r\n监听2执行回调出错");

                //用选择框改变事件关闭监听
                TCPListen2_CheckedChanged(null, null);
                return "";
            }

            string res = JsonConvert.SerializeObject(obj);
            changeListenText("\r\n收到终端2的请求在Form:" + res);
            return res;
        }

        private void SentTCP2_Click(object sender, EventArgs e)
        {
            try
            {
                if (tcpHello2 == null)
                {
                    MessageBox.Show("请先打开监听2");
                    return;
                }
                tcpHello2.SendHello("测试发送TCP请求222:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff"));
            }
            catch (Exception)
            {
            }
        }
    }
}
View Code

 

RabbitMQForm

namespace WinFormActiveMQ
{
    partial class RabbitMQForm
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.TestHello = new System.Windows.Forms.CheckBox();
            this.TCPHello = new System.Windows.Forms.CheckBox();
            this.textBox1 = new System.Windows.Forms.TextBox();
            this.TestRequestTcp = new System.Windows.Forms.Button();
            this.TCPListen2 = new System.Windows.Forms.CheckBox();
            this.TCPIp1 = new System.Windows.Forms.TextBox();
            this.label1 = new System.Windows.Forms.Label();
            this.TCPPort1 = new System.Windows.Forms.TextBox();
            this.label2 = new System.Windows.Forms.Label();
            this.TCPIp2 = new System.Windows.Forms.TextBox();
            this.TCPPort2 = new System.Windows.Forms.TextBox();
            this.SentTCP2 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // TestHello
            // 
            this.TestHello.AutoSize = true;
            this.TestHello.Location = new System.Drawing.Point(12, 12);
            this.TestHello.Name = "TestHello";
            this.TestHello.Size = new System.Drawing.Size(129, 19);
            this.TestHello.TabIndex = 0;
            this.TestHello.Text = "接收队列Hello";
            this.TestHello.UseVisualStyleBackColor = true;
            this.TestHello.CheckedChanged += new System.EventHandler(this.TestHello_CheckedChanged);
            // 
            // TCPHello
            // 
            this.TCPHello.AutoSize = true;
            this.TCPHello.Location = new System.Drawing.Point(216, 77);
            this.TCPHello.Name = "TCPHello";
            this.TCPHello.Size = new System.Drawing.Size(123, 19);
            this.TCPHello.TabIndex = 1;
            this.TCPHello.Text = "监听TCPHello";
            this.TCPHello.UseVisualStyleBackColor = true;
            this.TCPHello.CheckedChanged += new System.EventHandler(this.TCPHello_CheckedChanged);
            // 
            // textBox1
            // 
            this.textBox1.Location = new System.Drawing.Point(13, 248);
            this.textBox1.Multiline = true;
            this.textBox1.Name = "textBox1";
            this.textBox1.Size = new System.Drawing.Size(427, 160);
            this.textBox1.TabIndex = 2;
            // 
            // TestRequestTcp
            // 
            this.TestRequestTcp.Location = new System.Drawing.Point(345, 73);
            this.TestRequestTcp.Name = "TestRequestTcp";
            this.TestRequestTcp.Size = new System.Drawing.Size(122, 23);
            this.TestRequestTcp.TabIndex = 3;
            this.TestRequestTcp.Text = "发送TCP请求";
            this.TestRequestTcp.UseVisualStyleBackColor = true;
            this.TestRequestTcp.Click += new System.EventHandler(this.TestRequestTcp_Click);
            // 
            // TCPListen2
            // 
            this.TCPListen2.AutoSize = true;
            this.TCPListen2.Location = new System.Drawing.Point(216, 106);
            this.TCPListen2.Name = "TCPListen2";
            this.TCPListen2.Size = new System.Drawing.Size(67, 19);
            this.TCPListen2.TabIndex = 4;
            this.TCPListen2.Text = "监听2";
            this.TCPListen2.UseVisualStyleBackColor = true;
            this.TCPListen2.CheckedChanged += new System.EventHandler(this.TCPListen2_CheckedChanged);
            // 
            // TCPIp1
            // 
            this.TCPIp1.Location = new System.Drawing.Point(13, 75);
            this.TCPIp1.Name = "TCPIp1";
            this.TCPIp1.Size = new System.Drawing.Size(114, 25);
            this.TCPIp1.TabIndex = 5;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(12, 57);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(53, 15);
            this.label1.TabIndex = 6;
            this.label1.Text = "请求ip";
            // 
            // TCPPort1
            // 
            this.TCPPort1.Location = new System.Drawing.Point(144, 74);
            this.TCPPort1.Name = "TCPPort1";
            this.TCPPort1.Size = new System.Drawing.Size(66, 25);
            this.TCPPort1.TabIndex = 7;
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(141, 56);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(112, 15);
            this.label2.TabIndex = 8;
            this.label2.Text = "请求和监听端口";
            // 
            // TCPIp2
            // 
            this.TCPIp2.Location = new System.Drawing.Point(12, 106);
            this.TCPIp2.Name = "TCPIp2";
            this.TCPIp2.Size = new System.Drawing.Size(114, 25);
            this.TCPIp2.TabIndex = 9;
            // 
            // TCPPort2
            // 
            this.TCPPort2.Location = new System.Drawing.Point(144, 106);
            this.TCPPort2.Name = "TCPPort2";
            this.TCPPort2.Size = new System.Drawing.Size(66, 25);
            this.TCPPort2.TabIndex = 10;
            // 
            // SentTCP2
            // 
            this.SentTCP2.Location = new System.Drawing.Point(345, 108);
            this.SentTCP2.Name = "SentTCP2";
            this.SentTCP2.Size = new System.Drawing.Size(122, 23);
            this.SentTCP2.TabIndex = 11;
            this.SentTCP2.Text = "SentTCP2";
            this.SentTCP2.UseVisualStyleBackColor = true;
            this.SentTCP2.Click += new System.EventHandler(this.SentTCP2_Click);
            // 
            // RabbitMQForm
            // 
            this.ClientSize = new System.Drawing.Size(498, 417);
            this.Controls.Add(this.SentTCP2);
            this.Controls.Add(this.TCPPort2);
            this.Controls.Add(this.TCPIp2);
            this.Controls.Add(this.label2);
            this.Controls.Add(this.TCPPort1);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.TCPIp1);
            this.Controls.Add(this.TCPListen2);
            this.Controls.Add(this.TestRequestTcp);
            this.Controls.Add(this.textBox1);
            this.Controls.Add(this.TCPHello);
            this.Controls.Add(this.TestHello);
            this.Name = "RabbitMQForm";
            this.Text = "RabbitMQForm";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.CheckBox TestHello;
        private System.Windows.Forms.CheckBox TCPHello;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Button TestRequestTcp;
        private System.Windows.Forms.CheckBox TCPListen2;
        private System.Windows.Forms.TextBox TCPIp1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.TextBox TCPPort1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.TextBox TCPIp2;
        private System.Windows.Forms.TextBox TCPPort2;
        private System.Windows.Forms.Button SentTCP2;
    }
}
View Code

 

5、默认配置

  <appSettings>
    <add key="MQServerTLogPath" value="d:/WinFormActiveMQLog/" />
    <add key="RabbitMQHostName" value="192.168.0.233" />
    <add key="RabbitMQUserName" value="admin" />
    <add key="RabbitMQPassword" value="123456" />
    <add key="RabbitMQPort" value="5672" />
    <add key="RabbitMQVirtualHost" value="" />
    <add key="RabbitMQ_durable" value="true" />
    <add key="RabbitMQ_exclusive" value="false" />
    <add key="RabbitMQ_autoDelete" value="false" />
  </appSettings>

 

TCP监听demo

6、TCP监听类

using MQServer;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace TCPServer
{
    public class TCPServerT
    {

        /// <summary>
        /// 声明监听回调委托类型
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public delegate object ListenBackDelegate(object s);

        /// <summary>
        /// 监听状态
        /// </summary>
        public bool IsListening = false;

        static Dictionary<string, TCPServerT> tcps;//ip加端口唯一
        string ip; 
        int port;
        private TcpClient tcpClient;
        private Socket listener;
        private TCPServerT()
        {
        }
        private TCPServerT(string ip, int port) 
        {
            this.ip = ip;
            this.port = port;
        }

        /// <summary>
        /// 得到TCP服务实例
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public static TCPServerT Instance(string ip, int port) 
        {
            if (tcps == null) 
            {
                tcps = new Dictionary<string, TCPServerT>();
            }
            string key = ip + port;
            if (tcps.Keys.Contains(key))
            {
                return tcps[key];
            }
            else 
            {
                TCPServerT nowTcpSetvice = new TCPServerT(ip, port);
                tcps.Add(key, nowTcpSetvice);
                return nowTcpSetvice;
            }
        }

        /// <summary>
        /// 发送TCP消息
        /// </summary>
        /// <param name="data"></param>
        public void Request(string data)
        {
            tcpClient = new TcpClient();
            tcpClient.Connect(IPAddress.Parse(ip), port);
            NetworkStream ntwStream = tcpClient.GetStream();
            if (ntwStream.CanWrite)
            {
                Byte[] bytSend = Encoding.UTF8.GetBytes(data);
                ntwStream.Write(bytSend, 0, bytSend.Length);
            }
            else
            {
                ntwStream.Close();
                tcpClient.Close();
                throw new Exception("无法写入互数据流");
            }
            ntwStream.Close();
            tcpClient.Close();
        }
        /// <summary>
        /// 发送TCP消息
        /// </summary>
        /// <param name="data"></param>
        public void Request(TCPServiceMsgModel model)
        {
            Request(JsonConvert.SerializeObject(model));
        }

        /// <summary>
        /// 监听数据开始
        /// </summary>
        /// <param name="back">两个监听回调都会执行</param>
        /// <param name="back2">正常时调用back2(obj),失败时调用back2(null)</param>
        public void Listen(ListenBackDelegate back, ListenBackDelegate back2=null)
        {
            if (IsListening) 
            {
                throw new Exception("端口"+ port +"已处于监听状态,线程中只能存在一个Ip端口连接。");
            }

            IsListening = true;
            listener = new Socket(AddressFamily.InterNetwork,
                SocketType.Stream, ProtocolType.Tcp);

            IPAddress ipAddress;
            if (string.IsNullOrWhiteSpace(ip))
            {
                ipAddress = IPAddress.Any;
            }
            else 
            {
                ipAddress = IPAddress.Parse(ip);
            }

            listener.Bind(new IPEndPoint(ipAddress, port));

            //不断监听端口
            while (IsListening)
            {
                try
                {
                    listener.Listen(0);
                    Socket socket = listener.Accept();
                    NetworkStream ntwStream = new NetworkStream(socket);
                    StreamReader strmReader = new StreamReader(ntwStream);
                    var objs = new object[] { strmReader.ReadToEnd() };
                    try
                    {
                        back.Invoke(objs);
                        if (back2 != null)
                        {
                            back2.Invoke(objs);
                        }
                    }
                    catch (Exception ex)
                    {
                        //回调失败时,执行back2传空,判断为空处理回调失败
                        if (back2 != null)
                        {
                            back2.Invoke(null);
                        }

                        TLogHelper.Error(ex.Message, "回调失败");

                        ////执行失败时是否终止监听
                        //CloseListen();
                        throw ex;
                    }
                    finally 
                    {
                        socket.Close();
                    }
                }
                catch (Exception)
                {
                }
            }
            CloseListen();
        }

        /// <summary>
        /// 关闭监听
        /// </summary>
        public void CloseListen ()
        {
            if (listener != null)
            {
                try
                {
                    listener.Shutdown(SocketShutdown.Both);
                }
                catch (Exception)
                {
                }
                listener.Dispose();
                listener.Close();
            }
            IsListening = false;
        }
    }
}
View Code

 

数据格式类

namespace TCPServer
{
    public class TCPServiceMsgModel
    {
        /// <summary>
        /// 业务名
        /// </summary>
        public string BLLName { get; set; }

        /// <summary>
        /// 业务数据
        /// </summary>
        public object Data { get; set; }
    }
}
View Code

 

7、BLL业务

BaseTCPBLL

using System;
using System.Threading;
namespace TCPServer
{
    public abstract class BaseTCPBLL: IDisposable
    {
        public bool IsListening
        {
            get
            {
                if (tcp == null)
                {
                    return false;
                }
                return tcp.IsListening;
            }
        }

        private TCPServerT tcp;
        private TCPServerT tcpSend;
        private TCPServerT.ListenBackDelegate back2;//启动监听动作的线程的回调,由启动监听方法传入
        private Thread thrListener;
        private BaseTCPBLL(){}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="requestIp">请求ip</param>
        /// <param name="requestPort">请求端口</param>
        /// <param name="listenIp">监听ip</param>
        /// <param name="listenPort">监听端口</param>
        protected BaseTCPBLL(string requestIp,int requestPort, string listenIp,int listenPort)
        {
            //实例化Tcp服务
            tcp = TCPServerT.Instance(listenIp, listenPort);
            tcpSend = TCPServerT.Instance(requestIp, requestPort);
        }
        #region  TCP服务
        /// <summary>
        /// 开始监听客户请求处理业务
        /// ,正常时调用back2(obj),失败时调用back2(null)
        /// </summary>
        public Thread ListenStart(TCPServerT.ListenBackDelegate back2 = null)
        {
            if (IsListening) 
            {
                return thrListener;
            }

            this.back2 = back2;
            thrListener = new Thread(new ThreadStart(Listen));
            thrListener.Start();

            return thrListener;
        }

        /// <summary>
        /// 监听执行
        /// </summary>
        private void Listen()
        {
            tcp.Listen(ListenClientBack, back2);
        }

        /// <summary>
        /// 关闭监听
        /// </summary>
        public void CloseListen()
        {
            tcp.CloseListen();
        }

        /// <summary>
        /// 收到终端的请求后回调
        /// </summary>
        protected abstract string ListenClientBack(object obj);
        #endregion

        /// <summary>
        /// 发送请求
        /// </summary>
        protected void Request(TCPServiceMsgModel model)
        {
            tcpSend.Request(model);
        }

        public void Dispose() 
        {
            tcp.CloseListen();
            tcpSend.CloseListen();
        }
    }
}
View Code

 

TCPTestHello:BaseTCPBLL

using MQServer;
using Newtonsoft.Json;
using TCPServer;

namespace BLL
{
    public class TCPTestHello:BaseTCPBLL
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="requestIp">请求ip,本机"127.0.0.1"</param>
        /// <param name="requestPort">请求端口</param>
        /// <param name="listenIp">监听ip,本机""</param>
        /// <param name="listenPort">监听端口</param>
        public TCPTestHello(string requestIp, int requestPort, string listenIp, int listenPort)
            :base(requestIp, requestPort, listenIp, listenPort)
        {
        }
        #region  TCP服务 

        /// <summary>
        /// 收到终端的请求后回调
        /// </summary>
        protected override string ListenClientBack(object obj)
        {
            var res = JsonConvert.SerializeObject(obj);
            //解析source,根据source中的BLLName方法名,执行不同业务

            TCPServiceMsgModel model;
            try
            {
                res = JsonConvert.DeserializeObject<string[]>(res)[0];
                model = JsonConvert.DeserializeObject<TCPServiceMsgModel>(res);
            }
            catch (System.Exception)
            {
                throw new System.Exception("TCP接收到对象不是本模块接受的格式!"+ res);
            }

            switch (model.BLLName)
            {
                case "Hello":
                    Hello(model.Data);
                    break;
                default:
                    break;
            }
            return res;
        }
        #endregion

        /// <summary>
        /// 发送Hello请求
        /// </summary>
        public void SendHello(object data)
        {
            Request(new TCPServiceMsgModel() { BLLName = "Hello", Data = data });
        }

        public void Hello(object data)
        {
            TLogHelper.Info(JsonConvert.SerializeObject(data), "接收到消息在TCPTestHello");
        }

    }
}
View Code

 

posted @ 2020-10-24 17:52  lanofsky  阅读(1226)  评论(0编辑  收藏  举报