一个用于测试的 HL7 Server。在过NIST的认证时,需要演示检验数据通过HL7进行传输,所以写了这工具。
HL7的消息解析和编码使用了NHapi。包含两个服务:
这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 NotifyEvent;
public virtual void OnNotifyEvent(NotifyEventArgs e)
{
EventHandler 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用于监听Socket端口,当Socket连接时,创建一个ReceiveTask进行业务处理。
Socket client = server.Accept();
if (client != null)
{
ReceiveTask rm = new ReceiveTask(client, this);
totalCount++;
}
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消息是常见的检验数据的消息。具体的结构可以查阅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用于把数据发给各业务节点
public class SendService : BaseService
{
public static int totalCount=0;
public static int donetotal=0;
protected override void Run()
{
List 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进行发送
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 GetTask()
{
List 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(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();
}
}