一个用于测试的 HL7 Server

说明

一个用于测试的 HL7 Server。在过NIST的认证时,需要演示检验数据通过HL7进行传输,所以写了这工具。

HL7的消息解析和编码使用了NHapi。包含两个服务:

  • ReceiveService
  • SendService

这2个服务都继承自 BaseService 

  public class BaseService{protected ManualResetEvent _ServiceExitEvent = new ManualResetEvent(true);protected ManualResetEvent _NeedStopEvent = new ManualResetEvent(true);public ManualResetEvent ServiceExitEvent { get { return _ServiceExitEvent; } }public enum ServiceStatus{ INITIAL, BUSY, IDLE, EXIT, ERROR };public ServiceStatus _ServiceStatus;public string _ServiceName = "";protected bool _ServiceStop = true;protected Thread _Thread = null;public event EventHandler<NotifyEventArgs> NotifyEvent;public virtual void OnNotifyEvent(NotifyEventArgs e){EventHandler<NotifyEventArgs> handler = NotifyEvent;if (handler != null){//e.Message += String.Format(" at {0}", DateTime.Now.ToString());handler(this, e);}}public virtual bool Start(){if (!_ServiceStop){OnNotifyEvent(new NotifyEventArgs("service is already running"));return false;}OnNotifyEvent(new NotifyEventArgs("service initial"));_Thread = new Thread(delegate(){_ServiceExitEvent.Reset();_NeedStopEvent.Reset();_ServiceStop = false;this.Run();OnNotifyEvent(new NotifyEventArgs("service exit"));_ServiceStop = true;_ServiceExitEvent.Set();});if (_ServiceName != ""){_Thread.Name = _ServiceName;}else{_Thread.Name = this.GetType().Name;}_Thread.Start();return true;}protected virtual void Run(){}protected bool NeedExit(int timeout){return _NeedStopEvent.WaitOne(timeout, false);}public virtual bool Stop(){_NeedStopEvent.Set();return true;}public void Close(){if (!_ServiceStop && (_Thread != null)){_Thread.Abort();}}}
}

ReceiveService

ReceiveService用于监听Socket端口,当Socket连接时,创建一个ReceiveTask进行业务处理。

                    Socket client = server.Accept();
                    if (client != null)
                    {
                        ReceiveTask rm = new ReceiveTask(client, this);
                        totalCount++;
                    }

ReceiveTask

ReceiveTask 启动一个 Thread进行数据处理。

    public class ReceiveTask
    {
        public static string parse_segment_def = "2.5.1";
        public ReceiveTask(Socket socket, ReceiveService svr)
        {
            Thread thread = new Thread(delegate()
                {
                    Receive(socket, svr);
                });
            thread.Name = "ReceiveMsg";
            thread.Start();
        } 

  protected void Receive(Socket socket, ReceiveService svr){IPEndPoint ieClient = socket.RemoteEndPoint as IPEndPoint;IPEndPoint ieServer = socket.LocalEndPoint as IPEndPoint;svr.OnNotifyEvent(new NotifyEventArgs("receive message from " + ieClient.ToString()));string msg = "";byte[] data = new byte[1024]; ;int recv = 0;while (true){recv = socket.Receive(data, data.Length, SocketFlags.None);if (recv == 0){break;}msg += Encoding.UTF8.GetString(data, 0, recv);}Hashtable ht = ParseMsg(msg);if (ht == null){svr.OnNotifyEvent(new NotifyEventArgs("parse message error"));return;}string id= AddToReceiveQueue(ieClient.ToString(), msg, ieServer.ToString(), ht);if (id == ""){svr.OnNotifyEvent(new NotifyEventArgs("fail to connect database"));return;}if (!AddToReminder(id)){svr.OnNotifyEvent(new NotifyEventArgs("fail to connect database"));return;}socket.Close();ReceiveService.donetotal++;}

 ORU_R01消息的处理

 ORU_R01消息是常见的检验数据的消息。具体的结构可以查阅HL7的手册。

                imsg = parser.Parse(msg, ReceiveTask.parse_segment_def);
                msgtype = imsg.GetType().Name;

                if (msgtype.Equals("ORU_R01", StringComparison.OrdinalIgnoreCase))
                {
                    ORU_R01 data = imsg as ORU_R01;
                    ht.Add("MessageType", msgtype); 
                    ht.Add("MessageControlID", data.MSH.MessageControlID.Value);             
                    ORU_R01_PATIENT_RESULT p=data.GetPATIENT_RESULT(0);
                    ht.Add("PatientID", p.PATIENT.PID.GetPatientIdentifierList(0).IDNumber.Value);
                }

SendService 

SendService用于把数据发给各业务节点

    public class SendService : BaseService{public static int totalCount=0;public static int donetotal=0;protected override void Run(){List<SendTask> ls = null;do{ls = SendTask.GetTask();totalCount += ls.Count;if (ls != null){foreach (SendTask st in ls){st.sendSvr = this;if (st.Send()){donetotal++;OnNotifyEvent(new NotifyEventArgs("id:" + st.id + "  has send successfully!"));}else{OnNotifyEvent(new NotifyEventArgs("id:" + st.id + "  has send fail!"));}}}} while (!NeedExit(1000));}}

SendTask 

 发送时使用SendTask进行发送 

    public class SendTask{public string id = "";public string sender = "";public string receiver = "";public string msg = "";public DateTime? msgtime = null;public SendService sendSvr;public SendTask(){}public static List<SendTask> GetTask(){List<SendTask> ls = null;string strSQL = "select top 20 * from SendQueue";ArrayList al = new ArrayList();DataTable dt = new DataTable();if (DataExecute.ExecuteSql(DataExecute.DBConnectString, strSQL, al, dt)){ls = new List<SendTask>(5);foreach (DataRow dr in dt.Rows){SendTask st = new SendTask();st.id = dr["id"].ToString().Trim();st.sender = dr["sender"].ToString().Trim();st.receiver = dr["receiver"].ToString().Trim();st.msg = dr["msg"].ToString().Trim();DateTime time = DateTime.Now;if (DateTime.TryParse(dr["msgtime"].ToString().Trim(), out time)){st.msgtime = time;}else{st.msgtime = null;}ls.Add(st);}}return ls;}public bool DeleteTask(){string strSQL = "insert into MsgQueue_Log(msgtime,sender,msg,receiver,senttime,sentsucc) values(?,?,?,?,getdate(),1)";ArrayList al = new ArrayList();al.Add(new OleDbParameter("msgtime", msgtime));al.Add(new OleDbParameter("sender", sender));al.Add(new OleDbParameter("msg", msg));al.Add(new OleDbParameter("receiver", receiver));DataExecute.ExecuteSql(DataExecute.DBConnectString, strSQL, al);strSQL = "delete from SendQueue where id=?";al = new ArrayList();al.Add(new OleDbParameter("id", id));return DataExecute.ExecuteSql(DataExecute.DBConnectString, strSQL, al);}public static void AddSendTask(string receiver, string msg){string strSQL = "insert into sendqueue(msg, receiver) values(?, ?)";ArrayList al = new ArrayList();al.Add(new OleDbParameter("msg", msg));al.Add(new OleDbParameter("receiver", receiver));DataExecute.ExecuteSql(DataExecute.DBConnectString, strSQL, al);}public bool Send(){IPAddress ip = null;int port = 0;string[] sa = receiver.Split(':');if (sa.Count() == 2){if (!IPAddress.TryParse(sa[0], out ip)){sendSvr.OnNotifyEvent(new NotifyEventArgs("there are some problems on ip adress;"));return false;}if (!int.TryParse(sa[1], out port)){sendSvr.OnNotifyEvent(new NotifyEventArgs("there are some problems on port or ip;"));return false;}}else{sendSvr.OnNotifyEvent(new NotifyEventArgs("there are some problems on ip and port adress;"));return false;}IPEndPoint ie = new IPEndPoint(ip, port);Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);if (client == null){return false;}try{client.Connect(ie);}catch (SocketException e){sendSvr.OnNotifyEvent(new NotifyEventArgs(e.Message));return false;}int i= client.Send(Encoding.UTF8.GetBytes(msg));client.Close();return DeleteTask();}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/67646.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

洛谷题目 P5994 [PA 2014] Kuglarz 题解 (本题较难)

题目传送门&#xff1a; P5994 [PA 2014] Kuglarz - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 前言&#xff1a; 本题涉及到最小生成树中的 kruskal 算法和并查集算法&#xff0c;图论基础概念两大知识点&#xff0c;瞎按对莱索没有学过图论的或最小生成树的可能会对这道…

消息队列篇--通信协议篇--网络通信模型(OSI7层参考模型,TCP/IP分层模型)

一、OSI参考模型&#xff08;Open Systems Interconnection Model&#xff09; OSI参考模型是一个用于描述和标准化网络通信功能的七层框架。它由国际标准化组织&#xff08;ISO&#xff09;提出&#xff0c;旨在为不同的网络设备和协议提供一个通用的语言和结构&#xff0c;以…

C# Winform制作一个登录系统

using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms;namespace 登录 {p…

记一次STM32编译生成BIN文件过大的问题(基于STM32CubeIDE)

文章目录 问题描述解决方法更多拓展 问题描述 最近在一个项目中使用了 STM32H743 单片机&#xff08;基于 STM32CubeIDE GCC 开发&#xff09;&#xff0c;它的内存分为了 DTCMRAM RAM_D1 RAM_D2 …等很多部分。其中 DTCM 的速度是比通常的内存要快的&#xff0c;缺点是不支持…

996引擎 -地图-添加安全区

996引擎 -地图-添加安全区 文件位置配置 cfg_startpoint.xls特效效果1345参考资料文件位置 文件位置服务端D:\996M2-lua\MirServer-lua\Mir200客户端D:\996M2-lua\996M2_debug\dev配置 cfg_startpoint.xls 服务端\Mir200\Envir\DATA\cfg_startpoint.xls 填歪了也有可能只画一…

【leetcode强化练习·二叉树】同时运用两种思维解题

本文参考labuladong算法笔记[【强化练习】同时运用两种思维解题 | labuladong 的算法笔记] 有的题目可以同时用「遍历」和「分解问题」两种思路来解&#xff0c;你可以利用这些题目训练自己的思维。 559. N 叉树的最大深度 | 力扣 | LeetCode | 给定一个 N 叉树&#xff0c;…

栈和队列特别篇:栈和队列的经典算法问题

图均为手绘,代码基于vs2022实现 系列文章目录 数据结构初探: 顺序表 数据结构初探:链表之单链表篇 数据结构初探:链表之双向链表篇 链表特别篇:链表经典算法问题 数据结构:栈篇 数据结构:队列篇 文章目录 系列文章目录前言一.有效的括号(leetcode 20)二.用队列实现栈(leetcode…

ios swift画中画技术尝试

继上篇&#xff1a;iOS swift 后台运行应用尝试失败-CSDN博客 为什么想到画中画&#xff0c;起初是看到后台模式里有一个picture in picture&#xff0c;去了解了后发现这个就是小窗口视频播放&#xff0c;方便用户执行多任务。看小窗口视频的同时&#xff0c;可以作其他的事情…

人生不止于职业发展

0 你的问题&#xff0c;我知道&#xff01; 工作意义是啥&#xff1f;职业发展在人生啥角色&#xff1f; 1 工作意义 农村人努力学习考上大学&#xff0c;得好工作&#xff0c;为逃离同村同龄人十几岁就工厂打工命运&#xff0c;过不凡人生&#xff0c;实现改命的唯一途径。…

【算法设计与分析】实验3:动态规划—最长公共子序列

目录 一、实验目的 二、实验环境 三、实验内容 四、核心代码 五、记录与处理 六、思考与总结 七、完整报告和成果文件提取链接 一、实验目的 掌握动态规划求解问题的思想&#xff1b;针对不同的问题&#xff0c;会利用动态规划进行设计求解以及时间复杂度分析&#xff0…

网关登录校验

网关登录校验 单体架构时我们只需要完成一次用户登录、身份校验&#xff0c;就可以在所有业务中获取到用户信息。而微服务拆分后&#xff0c;每个微服务都独立部署&#xff0c;不再共享数据。也就意味着每个微服务都需要做登录校验&#xff0c;这显然不可取。 鉴权思路分析 …

wxwidgets直接获取系统图标,效果类似QFileIconProvider

目前只做了windows版本&#xff0c;用法类似QFileIconProvider // 头文件 #ifndef WXFILEICONPROVIDER_H #define WXFILEICONPROVIDER_H#include <wx/wx.h> #include <wx/icon.h> #include <wx/image.h> #include <wx/bmpcbox.h> // Include for wxB…

【玩转全栈】--创建一个自己的vue项目

目录 vue介绍 创建vue项目 vue页面介绍 element-plus组件库 启动项目 vue介绍 Vue.js 是一款轻量级、易于上手的前端 JavaScript 框架&#xff0c;旨在简化用户界面的开发。它采用了响应式数据绑定和组件化的设计理念&#xff0c;使得开发者可以通过声明式的方式轻松管理数据和…

DS并查集(17)

文章目录 前言一、何为并查集&#xff1f;二、并查集的实现&#xff1f;并查集的初始化查找元素所在的集合判断两个元素是否在同一个集合合并两个元素所在的集合获取并查集中集合的个数并查集的路径压缩 三、来两道题练练手&#xff1f;省份的数量等式方程的可满足性 总结 前言…

minimind - 从零开始训练小型语言模型

大语言模型&#xff08;LLM&#xff09;领域&#xff0c;如 GPT、LLaMA、GLM 等&#xff0c;虽然它们效果惊艳&#xff0c; 但动辄10 Bilion庞大的模型参数个人设备显存远不够训练&#xff0c;甚至推理困难。 几乎所有人都不会只满足于用Lora等方案fine-tuing大模型学会一些新的…

【C++动态规划 离散化】1626. 无矛盾的最佳球队|2027

本文涉及知识点 C动态规划 离散化 LeetCode1626. 无矛盾的最佳球队 假设你是球队的经理。对于即将到来的锦标赛&#xff0c;你想组合一支总体得分最高的球队。球队的得分是球队中所有球员的分数 总和 。 然而&#xff0c;球队中的矛盾会限制球员的发挥&#xff0c;所以必须选…

Privacy Eraser,电脑隐私的终极清除者

Privacy Eraser 是一款专为保护用户隐私而设计的全能型软件&#xff0c;它不仅能够深度清理计算机中的各类隐私数据&#xff0c;还提供了多种系统优化工具&#xff0c;帮助用户提升设备的整体性能。通过这款软件&#xff0c;用户可以轻松清除浏览器历史记录、缓存文件、Cookie、…

【数据结构与算法】AVL树的插入与删除实现详解

文章目录 前言Ⅰ. AVL树的定义Ⅱ. AVL树节点的定义Ⅲ. AVL树的插入Insert一、节点的插入二、插入的旋转① 新节点插入较高左子树的左侧&#xff08;左左&#xff09;&#xff1a;右单旋② 新节点插入较高右子树的右侧&#xff08;右右&#xff09;&#xff1a;左单旋③ 新节点插…

SCRM开发为企业提供全面客户管理解决方案与创新实践分享

内容概要 在当今的商业环境中&#xff0c;客户关系管理&#xff08;CRM&#xff09;变得越来越重要。而SCRM&#xff08;社交客户关系管理&#xff09;作为一种新兴的解决方案&#xff0c;正在帮助企业彻底改变与客户的互动方式。快鲸SCRM是一个引人注目的工具&#xff0c;它通…

【C/C++】区分0、NULL和nullptr

&#x1f984;个人主页:小米里的大麦-CSDN博客 &#x1f38f;所属专栏:C_小米里的大麦的博客-CSDN博客 &#x1f381;代码托管:C: 探索C编程精髓&#xff0c;打造高效代码仓库 (gitee.com) ⚙️操作环境:Visual Studio 2022 目录 1. 0 和空指针 2. NULL 3. nullptr 总结 …