宿主是自己写的winform窗体程序,这个监听器跑在后台线程,用户开启监听后,仍然可以在界面进行其他操作
勾选checkbox,启动监听器,事件如下:
private void ckbStartListen_CheckedChanged(object sender, EventArgs e)
{
int port = 0;
if (!int.TryParse(tbServerPort.Text.Trim(), out port) && ckbStartListen.Checked)
{
MessageBox.Show("监听端口填写错误");
tbServerPort.Focus();
ckbStartListen.Checked = false;
return;
}
//勾选启动监听并且线程不忙时,可以开启监听
if (ckbStartListen.Checked)
{
if (backgroundWorker1.IsBusy)
{
MessageBox.Show("线程正忙,请稍后再试");
ckbStartListen.Checked = false;
return;
}
backgroundWorker1.RunWorkerAsync(port);
label16.Text = "正在监听";
label16.ForeColor = Color.Green;
tbServerPort.Enabled = false;
}
else
{
try
{
if (backgroundWorker1.IsBusy)
{
//停止
backgroundWorker1.CancelAsync();
label16.Text = "正在断开连接,请等待几秒";
label16.ForeColor = Color.Red;
//给自己发一个连接,以通知异步线程停止监听
TcpClient client = new TcpClient();
string hostName = Dns.GetHostName();
client.Connect(IPAddress.Parse("127.0.0.1"), port);
if (client.Connected)
client.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
后台线程backgroundWorker1的各个事件
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//进度报告
tbReportInfo.Text = string.Join("\r\n", Reports);
tbSuccessNum.Text = PKSuccess.ToString();
tbFailNum.Text = PKFail.ToString();
tbUploadTime.Text = (PKFail + PKSuccess).ToString();
tbServerPort.Enabled = false;
if (!string.IsNullOrEmpty(DevState))
tbDevState.Text = DevState;
if (!string.IsNullOrEmpty(DoorState))
tbDoorState.Text = DoorState;
tbWallShake.Text = KBAlert+"";
tbDoorShake.Text = KMAlert+"";
tbOutTime.Text = OutTimeAlert+"";
//dgvPKinfo.DataSource = null;
//dgvPKinfo.DataSource = pklist;
//必须这样绑定才能刷新列表,晕
dgvPKinfoRef();
dgvLockInfoRef();
dgvJCRef();
//dgvLockInfo.DataSource = lockList;
//dgvJC.DataSource = cjShowlist;
}
private void dgvPKinfoRef()
{
BindingList bd = new BindingList();
dgvPKinfo.DataSource = bd;
foreach (PKModel P in pklist)
{
bd.Add(P);
}
}
private void dgvLockInfoRef()
{
BindingList bd = new BindingList();
dgvLockInfo.DataSource = bd;
foreach (LockModel P in lockList)
{
bd.Add(P);
}
}
private void dgvJCRef()
{
BindingList bd = new BindingList();
dgvJC.DataSource = bd;
foreach (CJModel_Show P in cjShowlist)
{
bd.Add(P);
}
}
///
/// 将异步执行的操作
///
///
///
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
int port = int.Parse(e.Argument.ToString());
int js = 0;
//创建服务器监听
TcpListener server = new TcpListener(IPAddress.Any, port);
//最大可支持10个挂起的连接
server.Start(10);
while (true)
{
try
{
//接收连接请求
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
Common.WriteLog("用户取消了监听");
server.Stop();
return;
}
TcpClient client = server.AcceptTcpClient();
client.ReceiveTimeout = 10 * 1000;//10秒无数据则停止等待
NetworkStream stream = client.GetStream();
#region 已连接
byte[] buffer = new byte[4096];
while (true)
{
try
{
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
Common.WriteLog("用户取消了监听");
stream.Close();
client.Client.Shutdown(SocketShutdown.Both);
client.Client.Close();
client.Close();
server.Stop();
return;
}
if (!client.Connected)//客户端断开后退出当前循环
break;
js++;
//从流数据里面获取数据
int lenth = stream.Read(buffer, 0, buffer.Length);
if (lenth > 0)
{
#region 接收
if (lenth <= 32)
{
Common.WriteLog("非法指令:" + BitConverter.ToString(buffer, 0, lenth));
continue;
}
//处理流数据
Common.WriteLog("未解密设备请求:" + BitConverter.ToString(buffer, 0, lenth));
string msg;
string retheadstr = "";
if (true)
{
//取出未加密的头部
byte[] rethead = new byte[32];
for (int i = 0; i < 32; i++)
{
rethead[i] = buffer[i];
}
retheadstr = Encoding.UTF8.GetString(rethead);
int len1 = Convert.ToInt32(retheadstr.Substring(0, 6));
//根据长度取出后续报文,不是16的倍数时需要同时取出补充的空格
int bc = 0;
if ((len1 - 32) % 16 != 0)
{
bc = 16 - ((len1 - 32) % 16);
}
byte[] retbody = new byte[len1 - 32 + bc];
for (int i = 0; i < retbody.Length; i++)
{
retbody[i] = buffer[i + 32];
}
//解密
msg = Common.Decrypt(retbody, AseKey).Trim();
if (cbOpenReport.Checked)
{
Common.WriteLog("解密设备请求:" + retheadstr + msg);
Reports.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-->设备请求:" + retheadstr + msg);
if (Reports.Count > 10)
{
Reports.RemoveRange(0, Reports.Count - 10);
}
}
}
else
{
msg = Encoding.UTF8.GetString(buffer, 0, lenth);
retheadstr = msg.Substring(0, 32);
msg = msg.Substring(32);
//修改List 试试
if (pklist == null)
pklist = new List();
pklist.Add(new PKModel()
{
Ex_BoxId = js + "",
Ex_BoxPower = "test" + js,
Ex_PartId = "test" + js,
Ex_PartStatus = "开启" + js
});
}
XmlDocument doc = new XmlDocument();
doc.LoadXml(msg);
string xml = string.Empty;
switch (retheadstr.Substring(6, 4))
{
case "2005": xml = PKResult(doc); break;
case "3001": xml = Report3001(doc); break;
case "3002": xml = Report3002(doc); break;
case "4001": xml = Report4001(doc); break;
default: Common.WriteLog("命令不存在:" + msg.Substring(6, 4)); break;
}
#endregion
#region 回复
//回复的头部信息用原来的
string head = retheadstr.Substring(6);
if (cbOpenReport.Checked)
{
Common.WriteLog("加密前服务器应答:" + ((head + xml).Length + 6).ToString().PadLeft(6, '0') + head + xml);
Reports.Add(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "-->服务器应答:" + ((head + xml).Length + 6).ToString().PadLeft(6, '0') + head + xml);
if (Reports.Count > 10)
{
Reports.RemoveRange(0, Reports.Count - 10);
}
}
//需要加密
byte[] newXml = Common.Encrypt(xml, AseKey);
byte[] newbyte = new byte[newXml.Length + 32];
byte[] headbyte = System.Text.Encoding.Default.GetBytes(head);
byte[] len = System.Text.Encoding.Default.GetBytes((newXml.Length + 32).ToString().PadLeft(6, '0'));
for (int i = 0; i < newbyte.Length; )
{
if (i < 6)
{
//前6位长度
for (int j = 0; j < len.Length; j++)
{
newbyte[i++] = len[j];
}
}
if (i < 32 && i >= 6)
{
//剩下的报文头
for (int j = 0; j < headbyte.Length; j++)
{
newbyte[i++] = headbyte[j];
}
}
if (i >= 32)
{
//报文体
for (int j = 0; j < newXml.Length; j++)
{
newbyte[i++] = newXml[j];
}
}
}
Common.WriteLog("加密后服务器应答:" + BitConverter.ToString(newbyte));
stream.Write(newbyte, 0, newbyte.Length);
stream.Flush();
#endregion
backgroundWorker1.ReportProgress(js);
}
else
{
break;
}
}
catch (SocketException)
{
try
{
Common.WriteLog("出现Socket异常,连接已断开");
client.Client.Shutdown(SocketShutdown.Both);
client.Client.Close();
client.Close();
}
catch { }
break;
}
catch (Exception ex)
{
Common.WriteLog("处理监听数据异常,异常信息:" + ex.Message + ";详细信息:" + ex.StackTrace);
stream.Close();
client.Close();
server.Stop();
break;
}
}
#endregion
}
catch(Exception ex)
{
Common.WriteLog("监听器出现异常,异常信息:" + ex.Message + ";详细信息:" + ex.StackTrace);
break;
}
}
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//完成,此判断是取消的,还是自然完成的
if (e.Cancelled)
MessageBox.Show("监听已终止");
else
MessageBox.Show("监听意外停止,请打开查看日志查看详情");
if (e.Error != null)
MessageBox.Show("监听异常停止,异常信息:" + e.Error.Message);
tbServerPort.Enabled = true;
label16.Text = "监听停止";
label16.ForeColor = Color.Red;
backgroundWorker1.Dispose();
}