注意连接队列服务器时,参数必须和服务器配置一致
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: " + 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(); } } }
消息格式RabbitMQMsgModel
namespace MQServer { public class RabbitMQMsgModel { /// <summary> /// 业务名 /// </summary> public string BLLName { get; set; } /// <summary> /// 业务数据 /// </summary> public object Data { get; set; } } }
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(); } } }
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"); } } }
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; } } }
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(" 监听执行回调出错"); //用选择框改变事件关闭监听 TCPHello_CheckedChanged(null,null); return ""; } string res = JsonConvert.SerializeObject(obj); changeListenText(" 收到终端的请求在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(" 监听2执行回调出错"); //用选择框改变事件关闭监听 TCPListen2_CheckedChanged(null, null); return ""; } string res = JsonConvert.SerializeObject(obj); changeListenText(" 收到终端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) { } } } }
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; } }
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; } } }
数据格式类
namespace TCPServer { public class TCPServiceMsgModel { /// <summary> /// 业务名 /// </summary> public string BLLName { get; set; } /// <summary> /// 业务数据 /// </summary> public object Data { get; set; } } }
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(); } } }
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"); } } }