1.前言
公司的一个项目,智能停车系统,我负责的主要是微信公众平台的开发,和socket异步通讯这块,来完成云平台和停车收费软件之间的交互。
车辆出场处理流程图【点击查看】【图片太大存放相册里面】
2.WCF
移动终端发起支付请求的时候,云平台会调用我这边的wcf,废话不多说,直接上代码。
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“ICalculationService”。 [ServiceContract] public interface ICalculationService { [OperationContract] string Calculation(string orderid, string parkId); [OperationContract] void PayNotify(string parkId, string orderid, string fee, string paytime, string actualFee); [OperationContract] string CarUpdate(string parkId, string carNo, string carTypeId, string startTime, string outTime, string recordTye,string key); }
// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“CalculationService”。 public class CalculationService : ICalculationService { public static AsynchronousSocketListener socketListener = null; /// <summary> ///请求计费 /// </summary> public string Calculation(string orderid, string parkId) { string result = Service1.socketListener.Calculation(int.Parse(parkId), orderid); return result; } /// <summary> /// 停车费支付通知 /// </summary> /// <returns></returns> public void PayNotify(string parkId, string orderid, string fee, string paytime, string actualFee) { Service1.socketListener.PayNotify(int.Parse(parkId), orderid,fee,paytime,actualFee); } /// <summary> /// 车辆信息同步 /// </summary> public string CarUpdate(string parkId, string carNo, string carTypeId, string startTime, string outTime, string recordTye,string key) { string result = Service1.socketListener.CarUpdate(int.Parse(parkId),carNo,carTypeId,startTime,outTime,recordTye,key); return result; } }
在来看一下,我们的这个公共帮助类关于WCF的一些配置帮助类。
using System;using System.Collections.Generic;using System.Linq;using System.Reflection;using System.Runtime.Serialization;using System.ServiceModel;using System.ServiceModel.Description;using System.ServiceModel.Security;using System.ServiceModel.Dispatcher;using System.Text;using System.Xml;namespace GoSunCN.OECD.CommunicationService.Common{ /// <summary> /// 传输参数方式 /// </summary> public enum EnumHttpBindingType { Small = 0, Normal = 1 } /// <summary> /// WCF 配置的帮助类 /// </summary> public static class WcfConfigHelper { /// <summary> /// 获取bassHTTP绑定 /// </summary> /// <returns></returns> public static BasicHttpBinding GetBasicHttpBinding(EnumHttpBindingType bindingType) { BasicHttpBinding ws = new BasicHttpBinding(BasicHttpSecurityMode.None); ws.CloseTimeout = new TimeSpan(0, 5, 0); ws.OpenTimeout = new TimeSpan(0, 5, 0); ws.ReceiveTimeout = new TimeSpan(0, 20, 0); ws.SendTimeout = new TimeSpan(0, 5, 0); ws.AllowCookies = false; ws.BypassProxyOnLocal = false; ws.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; ws.MaxBufferSize = 2147483647; ws.MaxBufferPoolSize = 2147483647; ws.MaxReceivedMessageSize = 2147483647; ws.MessageEncoding = WSMessageEncoding.Text; ws.TextEncoding = Encoding.UTF8; ws.TransferMode = TransferMode.Buffered; ws.UseDefaultWebProxy = true; ws.AllowCookies = false; ws.ReaderQuotas.MaxDepth = 2147483647; ws.ReaderQuotas.MaxStringContentLength = 2147483647; ws.ReaderQuotas.MaxArrayLength = 2147483647; ws.ReaderQuotas.MaxBytesPerRead = 2147483647; ws.ReaderQuotas.MaxNameTableCharCount = 2147483647; ws.Security.Mode = BasicHttpSecurityMode.None; ws.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; ws.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None; ws.Security.Transport.Realm = ""; ws.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName; ws.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default; return ws; } /// <summary> /// 获取默认HTTP绑定 /// </summary> /// <returns></returns> public static WSHttpBinding GetWsHttpBinding(EnumHttpBindingType bindingType) { WSHttpBinding ws = new WSHttpBinding(SecurityMode.None); ws.CloseTimeout = new TimeSpan(0, 5, 0); ws.OpenTimeout = new TimeSpan(0, 5, 0); ws.ReceiveTimeout = new TimeSpan(0, 20, 0); ws.SendTimeout = new TimeSpan(0, 5, 0); ws.BypassProxyOnLocal = false; ws.TransactionFlow = false; ws.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; ws.MaxBufferPoolSize = 2147483647;// 524288; ws.MaxReceivedMessageSize = 2147483647; ws.MessageEncoding = WSMessageEncoding.Text; ws.TextEncoding = Encoding.UTF8; ws.UseDefaultWebProxy = true; ws.AllowCookies = false; ws.ReaderQuotas.MaxDepth = 2147483647; ws.ReaderQuotas.MaxStringContentLength = 2147483647; ws.ReaderQuotas.MaxArrayLength = 2147483647; ws.ReaderQuotas.MaxBytesPerRead = 2147483647; ws.ReaderQuotas.MaxNameTableCharCount = 2147483647; ws.ReliableSession.Ordered = true; ws.ReliableSession.InactivityTimeout = new TimeSpan(23, 59, 0); ws.ReliableSession.Enabled = true; ws.Security.Mode = SecurityMode.None; ws.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; ws.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None; ws.Security.Transport.Realm = ""; ws.Security.Message.ClientCredentialType = MessageCredentialType.Windows; ws.Security.Message.NegotiateServiceCredential = true; ws.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default; ws.Security.Message.EstablishSecurityContext = false; return ws; } /// <summary> /// 获取默认HTTP绑定(双工通信) /// </summary> /// <returns></returns> public static WSDualHttpBinding GetWsDualHttpBinding(EnumHttpBindingType bindingType) { WSDualHttpBinding ws = new WSDualHttpBinding(WSDualHttpSecurityMode.Message); ws.CloseTimeout = new TimeSpan(0, 5, 0); ws.OpenTimeout = new TimeSpan(0, 5, 0); ws.ReceiveTimeout = new TimeSpan(0, 20, 0); ws.SendTimeout = new TimeSpan(0, 5, 0); ws.BypassProxyOnLocal = false; ws.TransactionFlow = false; ws.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; ws.MaxBufferPoolSize = 2147483647;// 524288; ws.MaxReceivedMessageSize = 2147483647; ws.MessageEncoding = WSMessageEncoding.Text; ws.TextEncoding = Encoding.UTF8; ws.UseDefaultWebProxy = true; ws.ReaderQuotas.MaxDepth = 2147483647; ws.ReaderQuotas.MaxStringContentLength = 2147483647; ws.ReaderQuotas.MaxArrayLength = 2147483647; ws.ReaderQuotas.MaxBytesPerRead = 2147483647; ws.ReaderQuotas.MaxNameTableCharCount = 2147483647; ws.ReliableSession.Ordered = true; ws.ReliableSession.InactivityTimeout = new TimeSpan(23, 59, 0); ws.Security.Message.ClientCredentialType = MessageCredentialType.Windows; ws.Security.Message.NegotiateServiceCredential = true; ws.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default; return ws; } /// <summary> /// 获取默认TCP绑定 /// </summary> /// <returns></returns> public static NetTcpBinding GetNetTcpBinding() { NetTcpBinding nettcp = new NetTcpBinding(SecurityMode.None); nettcp.CloseTimeout = new TimeSpan(0, 5, 0); nettcp.OpenTimeout = new TimeSpan(0, 5, 0); nettcp.ReceiveTimeout = new TimeSpan(0, 20, 0); nettcp.SendTimeout = new TimeSpan(0, 5, 0); nettcp.TransactionFlow = false; nettcp.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; nettcp.MaxBufferPoolSize = 1073741824; nettcp.MaxBufferSize = 1073741824; nettcp.MaxReceivedMessageSize = 1073741824; nettcp.ReaderQuotas.MaxDepth = 6553600; nettcp.ReaderQuotas.MaxStringContentLength = 2147483647; nettcp.ReaderQuotas.MaxArrayLength = 6553600; nettcp.ReaderQuotas.MaxBytesPerRead = 6553600; nettcp.ReaderQuotas.MaxNameTableCharCount = 6553600; nettcp.ReliableSession.Ordered = true; nettcp.ReliableSession.InactivityTimeout = new TimeSpan(23, 59, 0); nettcp.ReliableSession.Enabled = false; nettcp.Security.Mode = SecurityMode.None; nettcp.Security.Message.ClientCredentialType = MessageCredentialType.Windows; nettcp.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default; return nettcp; } /// <summary> /// 获取默认TCP绑定(双工通信) /// </summary> /// <returns></returns> public static NetTcpBinding GetDuplexBinding() { NetTcpBinding nettcp = new NetTcpBinding(SecurityMode.None); nettcp.CloseTimeout = new TimeSpan(0, 5, 0); nettcp.OpenTimeout = new TimeSpan(0, 5, 0); nettcp.ReceiveTimeout = new TimeSpan(0, 20, 0); nettcp.SendTimeout = new TimeSpan(0, 5, 0); nettcp.TransactionFlow = false; nettcp.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; nettcp.MaxBufferPoolSize = 1073741824; nettcp.MaxBufferSize = 1073741824; nettcp.MaxReceivedMessageSize = 1073741824; nettcp.ReliableSession.Ordered = true; nettcp.ReliableSession.InactivityTimeout = new TimeSpan(23, 59, 0); nettcp.ReliableSession.Enabled = false; nettcp.Security.Mode = SecurityMode.None; nettcp.Security.Message.ClientCredentialType = MessageCredentialType.Windows; nettcp.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default; return nettcp; } /// <summary> /// 获取默认命名管道绑定 /// </summary> /// <returns></returns> public static NetNamedPipeBinding GetNetPipeBinding() { //NetNamedPipeBinding NetNamedPipeBinding netnamepipe = new NetNamedPipeBinding(); netnamepipe.CloseTimeout = new TimeSpan(0, 5, 0); netnamepipe.OpenTimeout = new TimeSpan(0, 5, 0); netnamepipe.ReceiveTimeout = new TimeSpan(0, 20, 0); netnamepipe.SendTimeout = new TimeSpan(0, 5, 0); netnamepipe.TransactionFlow = false; netnamepipe.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard; netnamepipe.MaxBufferPoolSize = 1073741824; netnamepipe.MaxBufferSize = 1073741824; netnamepipe.MaxReceivedMessageSize = 1073741824; return netnamepipe; } /// <summary> /// 内部元数据行为 /// 配置文件:<serviceMetadata httpGetEnabled="true" /> /// </summary> /// <returns></returns> public static ServiceMetadataBehavior GetWsMetaBehavior() { ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); // 为避免泄漏元数据信息,请在部署前将以下值设置为 false 并删除上面的元数据终结点 behavior.HttpGetEnabled = true; // behavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; return behavior; } /// <summary> /// 内部调试行为 /// 配置文件:<serviceDebug includeExceptionDetailInFaults="true" /> /// </summary> /// <returns></returns> public static ServiceDebugBehavior GetserviceDebugBehavior() { ServiceDebugBehavior behavior = new ServiceDebugBehavior(); // 要接收故障异常详细信息以进行调试,请将下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 behavior.IncludeExceptionDetailInFaults = true; return behavior; } /// <summary> /// 内部流作用行为 /// 配置文件:<serviceThrottling maxConcurrentCalls ="100" maxConcurrentSessions ="100" maxConcurrentInstances ="100"/> /// </summary> /// <returns></returns> public static ServiceThrottlingBehavior GetserviceThrottlingBehavior() { ServiceThrottlingBehavior behavior = new ServiceThrottlingBehavior(); behavior.MaxConcurrentCalls = 100; behavior.MaxConcurrentSessions = 100; behavior.MaxConcurrentInstances = 100; return behavior; } /// <summary> /// 内部系列化参数设置 /// 配置文件:<dataContractSerializer maxItemsInObjectGraph="2147483647" /> /// </summary> /// <returns></returns> public static void SetdataContractSerializer(ServiceHost hostTemp) { Type t = hostTemp.GetType(); object obj = t.Assembly.CreateInstance("System.ServiceModel.Dispatcher.DataContractSerializerServiceBehavior", true, BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { false, Int32.MaxValue }, null, null); IServiceBehavior myServiceBehavior = obj as IServiceBehavior; if (myServiceBehavior != null) { hostTemp.Description.Behaviors.Add(myServiceBehavior); } } }}
3.接口说明
Calculation:请求计费
PayNotify:停车费支付通知
CarUpdate:车辆信息同步
4.Windos服务
由于windos服务比较稳定,在这里我们把他做成windos服务,一直在服务器上面运行。其中核心代码如下:
public partial class Service1 : ServiceBase { static ILog log = log4net.LogManager.GetLogger("MidServerLog"); private System.Timers.Timer timerDelay; protected override void OnStart(string[] args) { try { timerDelay = new System.Timers.Timer(3000); timerDelay.Elapsed += new System.Timers.ElapsedEventHandler(timerDelay_Elapsed); timerDelay.Start(); } catch (Exception ex) { log.Debug("OnStart:" + ex.ToString()); } } void timerDelay_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { timerDelay.Enabled = false; timerDelay.Close(); DoWork(); } public static AsynchronousSocketListener socketListener = null; private static ServiceHost m_ServiceHost = null; public static bool ServiceRuning { get { if (m_ServiceHost == null) return false; else if (m_ServiceHost.State != CommunicationState.Opened) return false; else return true; } } public Service1() { InitializeComponent(); } private static void DoWork() { socketListener = new AsynchronousSocketListener(); Thread thread = new Thread(socketListener.StartListening); thread.Start(); try { string ServiceUrl = string.Empty; ServiceUrl = System.Configuration.ConfigurationManager.AppSettings["wcf"].ToString(); //服务地址 Uri baseAddress = new Uri(ServiceUrl); m_ServiceHost = new ServiceHost(typeof(CalculationService), new Uri[] { baseAddress }); m_ServiceHost.AddServiceEndpoint(typeof(ICalculationService),
WcfConfigHelper.GetBasicHttpBinding(EnumHttpBindingType.Normal),
""); if (m_ServiceHost.Description.Behaviors.Find<System.ServiceModel.Description.ServiceMetadataBehavior>() == null) { System.ServiceModel.Description.ServiceMetadataBehavior svcMetaBehavior =
new System.ServiceModel.Description.ServiceMetadataBehavior();
svcMetaBehavior.HttpGetEnabled = true; svcMetaBehavior.HttpGetUrl = new Uri(ServiceUrl + "/Mex"); m_ServiceHost.Description.Behaviors.Add(svcMetaBehavior); } m_ServiceHost.Opened += new EventHandler(delegate(object obj, EventArgs e) { log.Debug("DoWork:" + "服务已经启动!"); }); m_ServiceHost.Open(); } catch (Exception e) { log.Debug("WCF服务启动失败:" + e.Message); } } static void HostFaulted(object sender, EventArgs e) { log.Error("通信机WCF遇到问题:" + e.ToString()); } protected override void OnStop() { AsynchronousSocketListener.StopListening(); if ((m_ServiceHost != null) && (m_ServiceHost.State != CommunicationState.Closed)) { m_ServiceHost.Close(); m_ServiceHost = null; } } }
5.接收物业公司客户端发送的数据
public class Bussiness { static ILog log = log4net.LogManager.GetLogger("MidServerLog"); public static Dictionary<string, orders> dicOrder = new Dictionary<string, orders>(); public static Dictionary<string, ParkMsg> dicParkMsg = new Dictionary<string, ParkMsg>(); public static void ProcessMethod(string content) { JObject jo = (JObject)JsonConvert.DeserializeObject(content); string method = jo["method"].ToString(); string param = content; switch (method) { case "calculation": CallBackCalculation(jo); break; case "payNotify": CallBackPayNotify(jo); break; case "carUpdate": CallBackCarUpdate(jo); break; default: break; } } /// <summary> /// 请求计费 /// </summary> private static void CallBackCalculation(JObject jo) { log.Debug("CallBackCalculation:" + "调用"); log.Debug("CallBackCalculation:" + "Jo的值:"+jo); double fee = double.Parse(jo["fee"].ToString()); double actualFee = double.Parse(jo["actualFee"].ToString()); string orderId = jo["orderid"].ToString(); if (dicOrder.ContainsKey(orderId)) { orders model = model = dicOrder[orderId]; if (model != null) { model.total_price = (decimal)fee; model.payablefee = (decimal)actualFee; model.updateTime = DateTime.Now; model.end_time = jo["time"].ToString(); log.Debug("CallBackCalculation:" + "调用结果,更新成功"); } } } /// <summary> /// 支付通知回调函数 /// </summary> private static void CallBackPayNotify(JObject jo) { log.Debug("CallBackPayNotify:" + "调用"); log.Debug("CallBackPayNotify:" + "Jo的值:" + jo); string code = jo["code"].ToString(); string orderId = jo["orderid"].ToString(); if (dicOrder.ContainsKey(orderId)) { orders model = model = dicOrder[orderId]; if (model != null) { model.updateTime = DateTime.Now; log.Debug("CallBackCalculation:" + "调用结果,更新成功"); } } log.Debug("CallBackCalculation:" + "调用结果,更新成功"); } /// <summary> /// 车辆信息同步 /// </summary> private static void CallBackCarUpdate(JObject jo) { log.Debug("CallBackCarUpdate:" + "调用"); log.Debug("CallBackCarUpdate:" + "Jo的值:" + jo); string code = jo["code"].ToString(); string parkId = jo["parkId"].ToString(); if (dicParkMsg.ContainsKey(parkId)) { ParkMsg model = model = dicParkMsg[parkId]; if (model != null) { model.UpdateTime = DateTime.Now; log.Debug("CallBackCarUpdate:" + "调用结果,更新成功"); } } }
}
6.Socket核心代码
public class AsynchronousSocketListener
{
static ILog log = log4net.LogManager.GetLogger("MidServerLog"); private Dictionary<string, Socket> clientList = new Dictionary<string, Socket>(); public static ManualResetEvent allDone = new ManualResetEvent(false); private static Socket listener; private int _port = 10000; public static void StopListening() { listener.Close(); }
public int Port { set { _port = value; } }
public bool IsStart { get { return listener.IsBound; } }
public void StartListening() { byte[] bytes = new Byte[1024]; string serverIP = System.Configuration.ConfigurationManager.AppSettings["ServerIP"]; IPAddress ipAddress = IPAddress.Parse(serverIP); IPEndPoint localEndPoint = new IPEndPoint(ipAddress, _port); listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(localEndPoint); listener.Listen(100); while (true) { allDone.Reset(); listener.BeginAccept(new AsyncCallback(AcceptCallback), listener); log.Info("启动监听!"); allDone.WaitOne(); } }
public Socket GetParkSocket(int parkId) { lock (clientList) { foreach (KeyValuePair<string, Socket> kvp in clientList) { if (kvp.Key.StartsWith(parkId.ToString() + "-")) { return kvp.Value; } } return null; } }
private void AcceptCallback(IAsyncResult ar) { allDone.Set(); Socket listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); StateObject state = new StateObject(); state.workSocket = handler; try { handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } catch(Exception ex) { log.Debug("AcceptCallback:" + ex.ToString()); } }
private void ReadCallback(IAsyncResult ar) { StateObject state = (StateObject)ar.AsyncState; Socket handler = state.workSocket; int bytesRead = 0; if (handler.Connected) { try { bytesRead = handler.EndReceive(ar); } catch (Exception ex) { log.Debug("ReadCallback:"+ex.ToString()); handler.Close(); } if (bytesRead > 0) { String content = String.Empty; content = Encoding.UTF8.GetString(state.buffer, 0, bytesRead); if (content.Length > 0) { ProcessCmd(handler, content); try { handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } catch (Exception ex) { log.Debug("ReadCallback:" + ex.ToString()); } } else { try { handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0, new AsyncCallback(ReadCallback), state); } catch (Exception ex) { log.Debug("ReadCallback:" + ex.ToString()); } } } } }
private void ProcessCmd(Socket handler, String content) { content = content.Replace("\r", "").Replace("\n", "").Replace("<EOF>", ""); JObject jo = null; try { jo = (JObject)JsonConvert.DeserializeObject(content); } catch (Exception ex) { log.Debug("ProcessCmd:" + ex.ToString()); } if (jo != null) { try { string method = jo["method"].ToString(); if (method.ToLower() == "login") { JsonLogin jsonLogin = JsonConvert.DeserializeObject<JsonLogin>(content); Login(jsonLogin, handler); } else { Bussiness.ProcessMethod(content); } } catch (Exception ex) { log.Debug("ProcessCmd:" + ex.ToString()); } } }
public void Send(string key, string data) { if (clientList.ContainsKey(key)) { Socket handler = clientList[key]; if (handler != null) { try { Send(handler, data); } catch (Exception ex) { log.Debug("Send:" + ex.ToString()); } } } }
private static void Send(Socket handler, String data) { if (handler != null) { byte[] byteData = Encoding.UTF8.GetBytes(data); try { handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler); } catch (Exception ex) { log.Debug("Send:" + ex.ToString()); } } }
private static void SendCallback(IAsyncResult ar) { Socket handler = (Socket)ar.AsyncState; int bytesSent = handler.EndSend(ar); }
private void Login(JsonLogin jsonLogin, Socket handler) { lock (clientList) { if (clientList.ContainsKey(jsonLogin.param.parkId.ToString() + "-" + jsonLogin.param.clientId)) { clientList.Remove(jsonLogin.param.parkId.ToString() + "-" + jsonLogin.param.clientId); } else { log.Debug("Login:" + jsonLogin.param.parkId.ToString() + "-" + jsonLogin.param.clientId); } try { clientList.Add(jsonLogin.param.parkId.ToString() + "-" + jsonLogin.param.clientId, handler); if (Login(jsonLogin)) { Send(handler, "{\"method\": \"login\", \"code\": 0,\"msg\": \"登录成功!\"}"); log.Debug("登陆成功:" + jsonLogin.param.parkId.ToString()); } } catch (Exception ex) { log.Debug("Login:" + ex.ToString()); } } }
private bool Login(JsonLogin jsonLogin) { return true; }
用户通过移动端支付的时候,云平台要调用WCF请求支付的方法来请求停车场获取用户停车计费信息。
internal string Calculation(int parkId, string orderid) { lock (Bussiness.dicOrder) { log.Debug("Calculation:" + "调用"); string str = "{\"method\":\"calculation\",\"param\":{\"orderid\":\"" + orderid + "\"}}"; orders model = new orders(); model.orderid = orderid; model.parentid = parkId.ToString(); if (Bussiness.dicOrder.ContainsKey(orderid)) { Bussiness.dicOrder.Remove(orderid); } Bussiness.dicOrder.Add(orderid, model); AsynchronousSocketListener.Send(GetParkSocket(parkId), str);//通过socket发送数据给物业公司的客户端 log.Info("Send:发送数据:" + str); for (int i = 0; i <= 12; i++) { if (Bussiness.dicOrder.ContainsKey(orderid)) { orders model2 = Bussiness.dicOrder[orderid]; if (model2 != null && model2.updateTime != null)//此处通过轮询检查是否收到停车场发送过来的json数据 { string strFee = model2.total_price.ToString() == "" ? "0" : model2.total_price.ToString(); string strpayablefee = model2.payablefee.ToString() == "" ? "0" : model2.payablefee.ToString(); string end_time = model2.end_time; string result = "{\"fee\": " + strFee + ",\"actualFee\": " + strpayablefee + ",\"end_time\":\"" + end_time + "\"}"; if (Bussiness.dicOrder.ContainsKey(orderid)) { Bussiness.dicOrder.Remove(orderid); } log.Debug("来自" + parkId .ToString()+ "的Calculation:" + "调用结果:" + result); return result; } } Thread.Sleep(500); } if (Bussiness.dicOrder.ContainsKey(orderid)) { Bussiness.dicOrder.Remove(orderid); } log.Debug("来自" + parkId.ToString() + "的Calculation:" + "调用结果:{\"code\":40001,\"msg\":\" token无效或过期\"}"); return "{\"code\":40001,\"msg\":\" token无效或过期\"}"; } }
/// <summary> /// 支付通知 /// </summary> /// <returns></returns> internal void PayNotify(int parkId, string orderid, string fee, string paytime, string actualFee) { lock (Bussiness.dicOrder) { log.Debug("PayNotify:" + "调用"); string str = "{\"method\":\"payNotify\",\"param\":{\"fee\": \"" + fee + "\",\"paytime\": \"" + paytime + "\",\"actualFee\":\"" + actualFee + "\",\"orderid\": \"" + orderid + "\"}}"; orders model = new orders(); model.orderid = orderid; model.parentid = parkId.ToString(); if (Bussiness.dicOrder.ContainsKey(orderid)) { Bussiness.dicOrder.Remove(orderid); } Bussiness.dicOrder.Add(orderid, model); AsynchronousSocketListener.Send(GetParkSocket(parkId), str); log.Info("Send:发送数据:" + str); for (int i = 0; i <= 12; i++) { if (Bussiness.dicOrder.ContainsKey(orderid)) { orders model2 = Bussiness.dicOrder[orderid]; if (model2 != null && model2.updateTime != null) { string result = "{\"msg\":\"测试支付通知\"}"; if (Bussiness.dicOrder.ContainsKey(orderid)) { Bussiness.dicOrder.Remove(orderid); } log.Debug("来自" + parkId.ToString() + "的PayNotify:" + "调用结果有返回测试成功:" + result); } } Thread.Sleep(500); } #endregion if (Bussiness.dicOrder.ContainsKey(orderid)) { Bussiness.dicOrder.Remove(orderid); } log.Debug("来自" + parkId.ToString() + "的PayNotify:" + "调用结果:无返回测试成功" + str); } }
管理员通过操作云平台后台管理系统后,需要调用WCF的车辆信息同步方法通知停车场同步消息。
/// <summary> /// 车辆信息同步 /// </summary> /// <returns></returns> internal string CarUpdate(int parkId,string carNo, string carTypeId, string startTime, string outTime, string recordTye,string key) { lock (Bussiness.dicParkMsg) { log.Debug("CarUpdate:" + "调用"); string str = "{\"method\":\"CarUpdate\",\"param\":{\"parkId\":\"" + parkId + "\",\"carNo\":\"" + carNo + "\",\"carTypeId\":\"" + carTypeId + "\",\"startTime\":\"" + startTime + "\",\"outTime\":\"" + outTime + "\",\"recordType\":\"" + recordTye + "\",\"key\":\"" + key + "\"}}"; ParkMsg model = new ParkMsg(); model.ParkId = parkId.ToString(); if (Bussiness.dicParkMsg.ContainsKey(parkId.ToString())) { Bussiness.dicParkMsg.Remove(parkId.ToString()); } Bussiness.dicParkMsg.Add(parkId.ToString(), model); AsynchronousSocketListener.Send(GetParkSocket(parkId), str); log.Info("Send:发送数据:" + str); for (int i = 0; i <= 12; i++) { if (Bussiness.dicOrder.ContainsKey(parkId.ToString())) { ParkMsg model2 = Bussiness.dicParkMsg[parkId.ToString()]; if (model2 != null && model2.UpdateTime != null) { string result = "{\"code\":0,\"msg\":\"车辆信息同步成功\"}"; if (Bussiness.dicOrder.ContainsKey(parkId.ToString())) { Bussiness.dicOrder.Remove(parkId.ToString()); } log.Debug("来自" + parkId.ToString() + "的CarUpdate:" + "调用结果:" + result); return result; } } Thread.Sleep(500); } if (Bussiness.dicParkMsg.ContainsKey(parkId.ToString())) { Bussiness.dicParkMsg.Remove(parkId.ToString()); } log.Debug("来自" + parkId.ToString() + "的CarUpdate:" + "调用结果:{\"code\":40001,\"msg\":\" token无效或过期\"}"); return "{\"code\":40001,\"msg\":\" token无效或过期\"}"; } }
}
整个系统中,最重要的是Socket,用户请求付费的时候,手机上面的APP或者微信公众号会调用云平台的请求计费接口,这个时候,云平台也不知道客户的停车费用到底是多少,这个时候,云平台就需要请求我们的Scoket,通过请求WCF暴露出来的方法,来获取客户的停车费用信息,每个停车场的计费信息不一样,每个停车场有一个固定的表示身份的ParkId,Socket会发送消息给停车场,这个请求的整个过程中,停车场和Socket服务端一致保持着连接,这个时候如果Socket服务端收到停车场的计费信息,就会发送给云平台,从而完成整个过程,其他两个接口方法原理也是类似.
公司的项目就不方便上传源码,如果你觉得本文不错,帮我推荐一下,感谢。
- 7楼wyd1520
- 即然你是用byte -gt;String 还有你的包里面有lt;EOFgt;,那你就干脆再加个lt;BOFgt;DATAlt;EOFgt; ,然后在StateObject 加个string Buffer做缓冲区,把所有的Recive过来的Data转成 string,state.Buffer+=Data;,//,while(state.Find()) //查找lt;BOFgt;lt;EOFgt; ,{, string= state.Queue() //出队, CallHandler()//呼叫你的业务。
- 6楼dark89757
- 看到ProcessCmd我就笑了,一个粘包都都没有!,Send也有没有线程并发处理!!
- Re: 枫伶忆
- @dark89757,新手嘛,请教下要如何优化了....
- 5楼查克拉的觉醒
- 项目就是不一样,很综合的说..
- Re: 枫伶忆
- @查克拉的觉醒,学习就需要分享,分享出来了,你要是没做过的你也可以学到一些东西,如果我有什么不足,你也可以给我指出来,这样才能共同进步是吧...感谢支持
- 4楼技术_菜鸟
- 不错,顶一下
- Re: 枫伶忆
- @技术_菜鸟,感谢支持
- 3楼Figgy
- 这么厉害,顶一下!
- Re: 枫伶忆
- @Figgy,感谢支持
- 2楼敷衍不起
- 好早啊。
- Re: 枫伶忆
- @敷衍不起,那像你可以搂着老婆美美的睡大觉,我们这样的穷屌丝,只有起来撸代码,才有机会逆袭女神....
- 1楼domaom
- 还不如直接用signalr+Web API,Web API直接返回的就是json或者xml了
- Re: 枫伶忆
- @domaom,这里不仅仅是要返回json数据就可以了,最只要的是移动端的APP,微信公众号,需要Java云平台提供稳定的接口,而和我们公司合作的停车场很多,目前有20几家吧,每个停车场的收费规则也不一样,停车场A也许停车一分钟1毛钱,停车场B也许是停车一分钟1.2毛钱,如果这样的话,用户在支付的时候,java云平台就需要连接停车场,获取停车费用,在这个过程中,java那边会掉用我们.net这边的WCF, Socket只是起到一个中间转发的作用,Java那边可能有更好的办法,项目比较急的时候,经理就叫我写的个Socket,我能力也是有限,只能写出这个样子,,,signalr+Web API可以实现我这样的需要?要是能够的话,跪求一个demo,再次感谢大神