最近闲来无事写了一个串口转网口的模拟机程序:
实现原理创建tcpserver监听端,接收客户端发送过来的信息,在通过com口转发出去。同样收到串口数据在通过服务端转发给客户端 如图
串口发送端代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
namespace SerailPortReciv
{
public partial class Form1 : Form
{
#region Var
private SerialPort EntitySerial = null;
private Thread ThreadRecive = null;
private Queue<ReciveInfo> ReciveQueue = new Queue<ReciveInfo>();
private byte[] ReciveBuffer = new byte[1024 * 2];
private bool IsLoopBool = false;
private int RecivePacketNU = 0;
private double ReciveBytesNU = 0;
private SynchronizationContext Context;
private int SendPacketNu = 0;
private Double SendBytesNu = 0;
private byte[] SendDataBytsBuffer = null;
private int SleepTiming = 0;
private Thread ThreadSendData = null;
private bool IsLoopSendData = false;
private bool IsRealShowRecInfo = false;
#endregion
public Form1()
{
InitializeComponent();
Context = SynchronizationContext.Current;
}
private void Form1_Load(object sender, EventArgs e)
{
comboBoxOddEvent.SelectedIndex = 1;
}
private void btnOpenSerail_Click(object sender, EventArgs e)
{
if (btnOpenSerail.Text == "开启串口")
{
if (!InitSerialPort())
{
MessageBox.Show("端口打开失败!" + txtCOM.Text);
return;
}
IsRealShowRecInfo = checkBoxRealShowInfo.Checked;
btnOpenSerail.Text = "关闭串口";
}
else
{
CloseCom();
btnOpenSerail.Text = "开启串口";
}
}
private bool InitSerialPort()
{
Parity par = Parity.None;
if (comboBoxOddEvent.SelectedItem != null)
{
switch (comboBoxOddEvent.SelectedItem.ToString().ToLower())
{
case "even":
par = Parity.Even;
break;
case "none":
par = Parity.None;
break;
case "odd":
par = Parity.Odd;
break;
default:
par = Parity.None;
break;
}
}
StopBits stopBit = StopBits.None;
switch (txtStopBit.Text)
{
case "1":
stopBit = StopBits.One;
break;
case "1.5":
stopBit = StopBits.OnePointFive;
break;
case "2":
stopBit = StopBits.Two;
break;
default:
stopBit = StopBits.None;
break;
}
try
{
EntitySerial = new SerialPort(txtCOM.Text.ToUpper(), int.Parse(txtBaudRate.Text), par, int.Parse(txtDataBit.Text), stopBit);
EntitySerial.Open();
}
catch (Exception)
{
return false;
}
IsLoopBool = true;
ThreadRecive = new Thread(ReciveMethod);
ThreadRecive.IsBackground = true;
ThreadRecive.Start();
return true;
}
/// <summary>
/// 接收数据线程
/// </summary>
void ReciveMethod()
{
while (IsLoopBool)
{
int recNU = EntitySerial.BytesToRead;
if (recNU > 0)
{
int reciveNu = EntitySerial.Read(ReciveBuffer, 0, recNU);
ReciveInfo entity = new ReciveInfo();
entity.Buffer = new byte[reciveNu];
entity.TimerString = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
Array.Copy(ReciveBuffer, entity.Buffer, reciveNu);
if (IsRealShowRecInfo)
{
ShowEntityInfo(entity);
}
else
{
ReciveQueue.Enqueue(entity);
}
RecivePacketNU++;
ReciveBytesNU += reciveNu;
Context.Post(ret => { labReciveInfo.Text = string.Format("{0}/{1}", RecivePacketNU, ReciveBytesNU); }, null);
}
}
}
/// <summary>
/// 关闭串口
/// </summary>
void CloseCom()
{
RecivePacketNU = 0;
ReciveBytesNU = 0;
Context.Post(ret => { labReciveInfo.Text = "总包数/总字节数"; }, null);
IsLoopBool = false;
if (EntitySerial != null)
{
EntitySerial.Close();
}
EntitySerial = null;
if (ThreadRecive != null && ThreadRecive.IsAlive)
{
ThreadRecive.Abort();
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
CloseCom();
CloseSendData();
}
/// <summary>
/// 显示接收到的数据
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnShowRecive_Click(object sender, EventArgs e)
{
lock (ReciveQueue)
{
while (ReciveQueue.Count > 0)
{
ShowEntityInfo(ReciveQueue.Dequeue());
Thread.Sleep(10);
}
}
}
private void ShowEntityInfo(ReciveInfo recv)
{
Context.Post(ret =>
{
txtShowRecive.AppendText(string.Format("[{0}] # Recive \r\n", recv.TimerString));
txtShowRecive.AppendText(GetBufferFormatHex(recv.Buffer) + "\r\n");
txtShowRecive.AppendText("\r\n");
}, null);
}
private string GetBufferFormatHex(byte[] bts)
{
StringBuilder sb = new StringBuilder();
foreach (byte itemBt in bts)
{
sb.Append(itemBt.ToString("X2") + " ");
}
return sb.ToString();
}
#region 定时发送数据
private void btnSendData_Click(object sender, EventArgs e)
{
if (btnSendData.Text == "发送数据")
{
bool retBool = int.TryParse(txtSendTiming.Text, out this.SleepTiming);
if (!retBool)
{
MessageBox.Show("定时发送时间不合法!");
return;
}
try
{
SendDataBytsBuffer = GetByteByHexString(txtSendData.Text);
}
catch
{
MessageBox.Show("待发送数据有误!");
return;
}
if (checkBoxTimnigSend.Checked)
{
IsLoopSendData = true;
ThreadSendData = new Thread(ProcSendData);
ThreadSendData.IsBackground = true;
ThreadSendData.Start();
btnSendData.Text = "停止";
}
else
{
try
{
txtShowRecive.AppendText(string.Format("[{0}] # Send \r\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")));
EntitySerial.Write(SendDataBytsBuffer, 0, SendDataBytsBuffer.Length);
txtShowRecive.AppendText(GetBufferFormatHex(SendDataBytsBuffer) + "[OK]\r\n");
}
catch (Exception)
{
txtShowRecive.AppendText(GetBufferFormatHex(SendDataBytsBuffer) + "[Error]\r\n");
}
finally
{
txtShowRecive.AppendText("\r\n");
}
}
}
else
{
CloseSendData();
btnSendData.Text = "发送数据";
}
}
/// <summary>
/// 结束发送线程
/// </summary>
private void CloseSendData()
{
IsLoopSendData = false;
if (ThreadSendData != null && ThreadSendData.IsAlive)
{
ThreadSendData.Abort();
}
}
/// <summary>
/// 定时发送数据
/// </summary>
void ProcSendData()
{
while (IsLoopSendData)
{
if (EntitySerial != null && EntitySerial.IsOpen)
{
EntitySerial.Write(SendDataBytsBuffer, 0, SendDataBytsBuffer.Length);
SendBytesNu += SendDataBytsBuffer.Length;
SendPacketNu++;
Context.Post(ret => { labSendInfo.Text = SendPacketNu + "/" + SendBytesNu; }, null);
}
Thread.Sleep(SleepTiming);
}
}
//16进制字符串得到byte[]
private byte[] GetByteByHexString(string hexComTxt)
{
hexComTxt = hexComTxt.Replace(" ", "").Replace("\r\n", "").Replace("\t", "");
byte[] bytes = new byte[hexComTxt.Length / 2];
for (int i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hexComTxt.Substring(i * 2, 2), 16);
}
return bytes;
}
#endregion
private void btnResate_Click(object sender, EventArgs e)
{
SendPacketNu = 0;
SendBytesNu = 0;
Context.Post(ret => { labSendInfo.Text = "总包数/总字节数"; }, null);
}
private void txtShowRecive_DoubleClick(object sender, EventArgs e)
{
((TextBox)sender).Text = "";
}
private void checkBoxRealShowInfo_CheckedChanged(object sender, EventArgs e)
{
this.IsRealShowRecInfo = checkBoxRealShowInfo.Checked;
}
}
class ReciveInfo
{
public byte[] Buffer { get; set; }
public string TimerString { get; set; }
}
}
嗯功能比较完整。有兴趣可以下载源码:https://download.csdn.net/download/weixin_43542114/12888689