单独两个程序通过http服务监听完成数据通讯,主要实现思路如下:
1、程序一启动监听固定IP地址(也可以是任意IP)及固定端口的监听,收到http请求后对请求内容进行解析,并根据MessageType(逻辑代码)进行不同逻辑处理,根据处理结果告知http请求发送程序结果。
2、程序二启动监听固定IP地址(也可以是任意IP)及固定端口的监听,收到http请求后对请求内容进行解析,并根据MessageType(逻辑代码)进行不同逻辑处理,根据处理结果告知http请求发送程序结果。
注意:
1、如果两个程序需要互相通讯至少要求两个程序之前的端口不同
2、为达到量程序互相通讯目的,两个程序既要对固定IP(也可以是任意IP)端口进行监听,还要能够发送http请求。
3、为确保两个程序能够收到消息,程序一监听的端口必须是程序二请求的端口,程序二监听的端口必须是程序一请求的端口。
程序一代码如下:
被动接收数据时需要启动IP端口监听
/// <summary>
/// 通讯IP地址
/// </summary>
public string ListenerIp = "127.0.0.1";
/// <summary>
/// 指令下发监听端口
/// </summary>
private static string IssuePort = ConfigurationManager.AppSettings["IssuePort"];
/// <summary>
/// 数据上传监听端口
/// </summary>
private static string UploadPort = ConfigurationManager.AppSettings["UploadPort"];
/// <summary>
/// http监听对象
/// </summary>
public HttpListener listener;
public void Init()
{
try
{
//启动数据接收监听IP及端口
string listenerUrl = $"http://{ListenerIp}:{UploadPort}/";
listener = new HttpListener();
listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
listener.Prefixes.Add(listenerUrl);
listener.Start();
//开始监听
listener.BeginGetContext(ListenerHandle, listener); //开始监听
}
catch (Exception e)
{
OnWriteLogDebug($"启用数据监听失败!{e.Message}");
}
}
/// <summary>
/// http监听获取到数据后的回调事件
/// </summary>
/// <param name="result"></param>
private void ListenerHandle(IAsyncResult result)
{
JObject jobject = new JObject();
//继续异步监听
listener.BeginGetContext(ListenerHandle, null);
//获得context对象
var context = listener.EndGetContext(result);
HttpListenerRequest request = context.Request;
var response = context.Response;
如果是js的ajax请求,还可以设置跨域的ip地址与参数
context.Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域请求,通常设置为配置文件
//context.Response.AppendHeader("Access-Control-Allow-Headers", "ID,PW");//后台跨域参数设置,通常设置为配置文件
//context.Response.AppendHeader("Access-Control-Allow-Method", "post");//后台跨域请求设置,通常设置为配置文件
context.Response.ContentType = "text/plain;charset=UTF-8";//告诉客户端返回的ContentType类型为纯文本格式,编码为UTF-8
context.Response.AddHeader("Content-type", "application/x-www-form-urlencoded");//添加响应头信息
context.Response.ContentEncoding = Encoding.UTF8;
try
{
//当接收到请求后程序流会走到这里
Console.ForegroundColor = ConsoleColor.White;
Stream streams = request.InputStream;
StreamReader reader = new StreamReader(streams, Encoding.UTF8);
string requestData = reader.ReadToEnd();
OnWriteLogDebug("收到请求原始数据:" + requestData.ToString());
//数据解析逻辑
sdkCallback(requestData);
//接收到http消息后的数据返回
jobject.Add("code", 0);
jobject.Add("data", "");
jobject.Add("result", true);
}
catch (Exception ex)
{
OnWriteLogDebug($"数据解析异常:{ex.Message},时间:{ DateTime.Now.ToString()}\r\n");
jobject.Add("code", 1);
jobject.Add("data", "");
jobject.Add("result", false);
}
finally
{
String hingeString = Newtonsoft.Json.JsonConvert.SerializeObject(jobject);
var returnByteArr = Encoding.UTF8.GetBytes(hingeString);//设置客户端返回信息的编码*/
response.StatusCode = 200;
response.ContentType = "application/json";
response.ContentEncoding = Encoding.UTF8;
using (var stream = response.OutputStream)
{
//把处理信息返回到客户端
stream.Write(returnByteArr, 0, returnByteArr.Length);
}
}
}
/// <summary>
/// 采集到的数据解析
/// </summary>
/// <param name="szData"></param>
/// <param name="nDataLength"></param>
/// <returns></returns>
private bool sdkCallback(string szData)
{
try
{
Newtonsoft.Json.Linq.JObject data = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(szData);
string MessageType = data["MessageType"].ToString();
if (MessageType == "逻辑类型")
{
ItemInfo info = new ItemInfo();
info.DoorId = int.Parse(data["DoorId"].ToString());
info.DeviceType = int.Parse(data["DeviceType"].ToString());
info.EventType = (EmEventType)Enum.Parse(typeof(EmEventType), data["EventType"].ToString());
var Values = data["Values"].ToString();
//数据更新或入库
UpdateTag(info, Values);
}
}
catch (Exception ex)
{
OnWriteLogDebug("数据解析异常:" + ex);
return false;
}
return true;
}
程序一主动发送数据
private bool SendCommand(JObject jObject)
{
using (WebClient webClient = new WebClient())
{
try
{
webClient.Headers.Add(HttpRequestHeader.ContentType, "application/json");
string url = $"http://{ListenerIp}:{IssuePort}/";
byte[] bytesRtn = webClient.UploadData(url, Encoding.ASCII.GetBytes(jObject.ToString()));
string json = Encoding.UTF8.GetString(bytesRtn);
Newtonsoft.Json.Linq.JObject jobject = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(json);
OnWriteLogDebug("下发数据结果:" + jobject.ToString());
return (string)jobject["code"] == "0";
}
catch (Exception ex)
{
OnWriteLogError("SendCommand: "+ex.ToString());
return false;
}
}
}
程序二代码如下(代码与程序一基本一致):
被动接收数据时需要启动IP端口监听
/// <summary>
/// 接口与采集控制台通讯IP地址
/// </summary>
private static string ListenerIp = "127.0.0.1";
/// <summary>
/// 指令下发监听端口
/// </summary>
private static string IssuePort = ConfigurationManager.AppSettings["IssuePort"];
/// <summary>
/// 数据上传监听端口
/// </summary>
private static string UploadPort = ConfigurationManager.AppSettings["UploadPort"];
static void Main(string[] args)
{
try
{
listener = new HttpListener();
listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
string listenerUrl = $"http://{ListenerIp}:{IssuePort}/";
listener.Prefixes.Add(listenerUrl);
listener.Start();
listener.BeginGetContext(ListenerHandle, listener); //开始监听
}
catch (Exception ex)
{
Console.WriteLine("指令下发端口监听任务启动失败:" + ex.Message);
}
finally
{
Console.ReadLine();
}
}
private static void ListenerHandle(IAsyncResult result)
{
JObject jobject = new JObject();
//继续异步监听
listener.BeginGetContext(ListenerHandle, null);
//获得context对象
var context = listener.EndGetContext(result);
HttpListenerRequest request = context.Request;
var response = context.Response;
如果是js的ajax请求,还可以设置跨域的ip地址与参数
context.Response.AppendHeader("Access-Control-Allow-Origin", "*");//后台跨域请求,通常设置为配置文件
//context.Response.AppendHeader("Access-Control-Allow-Headers", "ID,PW");//后台跨域参数设置,通常设置为配置文件
//context.Response.AppendHeader("Access-Control-Allow-Method", "post");//后台跨域请求设置,通常设置为配置文件
context.Response.ContentType = "text/plain;charset=UTF-8";//告诉客户端返回的ContentType类型为纯文本格式,编码为UTF-8
context.Response.AddHeader("Content-type", "application/x-www-form-urlencoded");//添加响应头信息
context.Response.ContentEncoding = Encoding.UTF8;
try
{
//当接收到请求后程序流会走到这里
Console.ForegroundColor = ConsoleColor.White;
Stream streams = request.InputStream;
StreamReader reader = new StreamReader(streams, Encoding.UTF8);
string requestData = reader.ReadToEnd();
Console.WriteLine($"指令下发接收接001{requestData},时间:{ DateTime.Now.ToString()}\r\n");
Newtonsoft.Json.Linq.JObject json = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(requestData);
Console.WriteLine($"指令下发接收接002{json.ToString()},时间:{ DateTime.Now.ToString()}\r\n");
bool result1 = false;//返回数据类型
#region 接收命令解析处理开始
if (json["dataType"].ToString() == "逻辑类型")
{
string UserName = (string)json["UserName"];
string Password = (string)json["Password"];
//逻辑代码
result1 = Connect(UserName, Password);
}
else
{
Console.WriteLine($"指令下发失败,未识别的指令信息,时间:{ DateTime.Now.ToString()}\r\n");
}
#endregion 接收命令解析处理结束
if (result1)
{
jobject.Add("code", 0);
jobject.Add("data", "");
jobject.Add("result", true);
}
else
{
jobject.Add("code", 1);
jobject.Add("data", "");
jobject.Add("result", false);
}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
jobject.Add("code", 1);
jobject.Add("data", "");
jobject.Add("result", false);
}
finally
{
String hingeString = Newtonsoft.Json.JsonConvert.SerializeObject(jobject);
var returnByteArr = Encoding.UTF8.GetBytes(hingeString);//设置客户端返回信息的编码*/
response.StatusCode = 200;
response.ContentType = "application/json";
response.ContentEncoding = Encoding.UTF8;
using (var stream = response.OutputStream)
{
//把处理信息返回到客户端
stream.Write(returnByteArr, 0, returnByteArr.Length);
}
}
}
程序二数据发送逻辑
private static void PrintMessage()
{
try
{
JObject jObject = new JObject();
jObject.Add("DoorId", int.Parse(ADV_Hid.InnerText));
jObject.Add("DeviceType", int.Parse(ADV_DeviceType.InnerText));
jObject.Add("EventType", EmEventType.ADVStatus.ToString());
jObject.Add("Values", ADV_Status.InnerText);
jObject.Add("MessageType", "messageQueue");
string result = WebServiceApp(jObject.ToString());
Console.WriteLine("请求结果:" + result);
}
catch (Exception ex)
{
Console.WriteLine("消息解析异常:" + sMessage + " " + ex.Message);
}
}
}
/// <summary>
/// 将回调事件的结果提交给接口
/// </summary>
/// <param name="param"></param>
/// <returns></returns>
public static string WebServiceApp(string param)
{
try
{
//转换输入参数的编码类型,获取bytep[]数组
byte[] byteArray = Encoding.UTF8.GetBytes(param);
//初始化新的webRequst
//1. 创建httpWebRequest对象
string pushUrl = $"http://{ListenerIp}:{UploadPort}/";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(pushUrl);
webRequest.KeepAlive = false;
webRequest.AllowAutoRedirect = true;
webRequest.CookieContainer = new CookieContainer();
//2. 初始化HttpWebRequest对象
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = byteArray.Length;
//3. 附加要POST给服务器的数据到HttpWebRequest对象(附加POST数据的过程比较特殊,它并没有提供一个属性给用户存取,需要写入HttpWebRequest对象提供的一个stream里面。)
Stream newStream = webRequest.GetRequestStream();//创建一个Stream,赋值是写入HttpWebRequest对象提供的一个stream里面
newStream.Write(byteArray, 0, byteArray.Length);
newStream.Close();
//4. 读取服务器的返回信息
HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse();
StreamReader php = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string phpend = php.ReadToEnd();
return phpend;
}
catch (Exception e)
{
return "请求异常" + e;
}
}
备注:由于当时实现功能时两个程序在同一台服务器,所以监听的IP地址都是127.0.0.1,如果要监听不同的IP地址,需要大家自行研究启动监听时的IP地址是对方的IP还是自己的IP。