本文参考《C#网络通信程序设计》(张晓明 编著)
程序界面如下图:
参数设置界面代码如下:
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;
namespace ComDemo
{
public partial class ComSet : Form
{
public ComSet()
{
InitializeComponent();
}
private void ComSet_Load(object sender, EventArgs e)
{
//串口
string[] ports = SerialPort.GetPortNames();
foreach (string port in ports)
{
cmbPort.Items.Add(port);
}
cmbPort.SelectedIndex = 0;
//波特率
cmbBaudRate.Items.Add("110");
cmbBaudRate.Items.Add("300");
cmbBaudRate.Items.Add("1200");
cmbBaudRate.Items.Add("2400");
cmbBaudRate.Items.Add("4800");
cmbBaudRate.Items.Add("9600");
cmbBaudRate.Items.Add("19200");
cmbBaudRate.Items.Add("38400");
cmbBaudRate.Items.Add("57600");
cmbBaudRate.Items.Add("115200");
cmbBaudRate.Items.Add("230400");
cmbBaudRate.Items.Add("460800");
cmbBaudRate.Items.Add("921600");
cmbBaudRate.SelectedIndex = 5;
//数据位
cmbDataBits.Items.Add("5");
cmbDataBits.Items.Add("6");
cmbDataBits.Items.Add("7");
cmbDataBits.Items.Add("8");
cmbDataBits.SelectedIndex = 3;
//停止位
cmbStopBit.Items.Add("1");
cmbStopBit.SelectedIndex = 0;
//佼验位
cmbParity.Items.Add("无");
cmbParity.SelectedIndex = 0;
}
private void bntOK_Click(object sender, EventArgs e)
{
//以下4个参数都是从窗体MainForm传入的
MainForm.strProtName = cmbPort.Text;
MainForm.strBaudRate = cmbBaudRate.Text;
MainForm.strDataBits = cmbDataBits.Text;
MainForm.strStopBits = cmbStopBit.Text;
DialogResult = DialogResult.OK;
}
private void bntCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
}
}
主界面代码如下:
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.IO;
using System.Threading;
namespace ComDemo
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private Thread getRecevice;
protected Boolean stop = false;
protected Boolean conState = false;
private StreamReader sRead;
string strRecieve;
bool bAccpet = false;
SerialPort sp = new SerialPort();//实例化串口通讯类
//以下定义4个公有变量,用于参数传递
public static string strProtName = "";
public static string strBaudRate = "";
public static string strDataBits = "";
public static string strStopBits = "";
private void MainForm_Load(object sender, EventArgs e)
{
groupBox1.Enabled = false;
groupBox2.Enabled = false;
this.toolStripStatusLabel1.Text = "端口号:端口未打开 | ";
this.toolStripStatusLabel2.Text = "波特率:端口未打开 | ";
this.toolStripStatusLabel3.Text = "数据位:端口未打开 | ";
this.toolStripStatusLabel4.Text = "停止位:端口未打开 | ";
this.toolStripStatusLabel5.Text = "";
}
//串口设计
private void btnSetSP_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
sp.Close();
ComSet dlg = new ComSet();
if (dlg.ShowDialog() == DialogResult.OK)
{
sp.PortName = strProtName;//串口号
sp.BaudRate = int.Parse(strBaudRate);//波特率
sp.DataBits = int.Parse(strDataBits);//数据位
sp.StopBits = (StopBits)int.Parse(strStopBits);//停止位
sp.ReadTimeout = 500;//读取数据的超时时间,引发ReadExisting异常
}
}
//打开/关闭串口
private void bntSwitchSP_Click(object sender, EventArgs e)
{
if (bntSwitchSP.Text == "打开串口")
{
if (strProtName != "" && strBaudRate != "" && strDataBits != "" && strStopBits != "")
{
try
{
if (sp.IsOpen)
{
sp.Close();
sp.Open();//打开串口
}
else
{
sp.Open();//打开串口
}
bntSwitchSP.Text = "关闭串口";
groupBox1.Enabled = true;
groupBox2.Enabled = true;
this.toolStripStatusLabel1.Text = "端口号:" + sp.PortName + " | ";
this.toolStripStatusLabel2.Text = "波特率:" + sp.BaudRate + " | ";
this.toolStripStatusLabel3.Text = "数据位:" + sp.DataBits + " | ";
this.toolStripStatusLabel4.Text = "停止位:" + sp.StopBits + " | ";
this.toolStripStatusLabel5.Text = "";
}
catch (Exception ex)
{
MessageBox.Show("错误:" + ex.Message, "C#串口通信");
}
}
else
{
MessageBox.Show("请先设置串口!", "RS232串口通信");
}
}
else
{
timer1.Enabled = false;
timer2.Enabled = false;
bntSwitchSP.Text = "打开串口";
if (sp.IsOpen)
sp.Close();
groupBox1.Enabled = false;
groupBox2.Enabled = false;
this.toolStripStatusLabel1.Text = "端口号:端口未打开 | ";
this.toolStripStatusLabel2.Text = "波特率:端口未打开 | ";
this.toolStripStatusLabel3.Text = "数据位:端口未打开 | ";
this.toolStripStatusLabel4.Text = "停止位:端口未打开 | ";
this.toolStripStatusLabel5.Text = "";
}
}
//发送数据
private void bntSendData_Click(object sender, EventArgs e)
{
if (sp.IsOpen)
{
try
{
sp.Encoding = System.Text.Encoding.GetEncoding("GB2312");
sp.Write(txtSend.Text);//发送数据
}
catch (Exception ex)
{
MessageBox.Show("错误:" + ex.Message);
}
}
else
{
MessageBox.Show("请先打开串口!");
}
}
//选择文件
private void btnOpenFile_Click(object sender, EventArgs e)
{
OpenFileDialog open = new OpenFileDialog();
open.InitialDirectory = "c\\";
open.RestoreDirectory = true;
open.FilterIndex = 1;
open.Filter = "txt文件(*.txt)|*.txt";
if (open.ShowDialog() == DialogResult.OK)
{
try
{
if (open.OpenFile() != null)
{
txtFileName.Text = open.FileName;
}
}
catch (Exception err1)
{
MessageBox.Show("文件打开错误! " + err1.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
}
//发送文件内容
private void bntSendFile_Click(object sender, EventArgs e)
{
string fileName = txtFileName.Text.Trim();
if (fileName == "")
{
MessageBox.Show("请选择要发送的文件!", "Error");
return;
}
else
{
//sRead = new StreamReader(fileName);
sRead = new StreamReader(fileName,Encoding.Default);//解决中文乱码问题
}
timer1.Start();
}
//发送文件时钟
private void timer1_Tick(object sender, EventArgs e)
{
string str1;
str1 = sRead.ReadLine();
if (str1 == null)
{
timer1.Stop();
sRead.Close();
MessageBox.Show("文件发送成功!", "C#串口通讯");
this.toolStripStatusLabel5.Text = "";
return;
}
byte[] data = Encoding.Default.GetBytes(str1);
sp.Write(data, 0, data.Length);
this.toolStripStatusLabel5.Text = " 文件发送中...";
}
//接收数据
private void btnReceiveData_Click(object sender, EventArgs e)
{
if (btnReceiveData.Text == "接收数据")
{
sp.Encoding = Encoding.GetEncoding("GB2312");
if (sp.IsOpen)
{
//timer2.Enabled = true; //使用主线程进行
//使用委托以及多线程进行
bAccpet = true;
getRecevice = new Thread(new ThreadStart(testDelegate));
//getRecevice.IsBackground = true;
getRecevice.Start();
btnReceiveData.Text = "停止接收";
}
else
{
MessageBox.Show("请先打开串口");
}
}
else
{
//timer2.Enabled = false;
bAccpet = false;
try
{ //停止主监听线程
if (null != getRecevice)
{
if (getRecevice.IsAlive)
{
if (!getRecevice.Join(100))
{
//关闭线程
getRecevice.Abort();
}
}
getRecevice = null;
}
}
catch { }
btnReceiveData.Text = "接收数据";
}
}
private void testDelegate()
{
reaction r = new reaction(fun);
r();
}
//用于接收数据的定时时钟
private void timer2_Tick(object sender, EventArgs e)
{
string str = sp.ReadExisting();
string str2 = str.Replace("\r", "\r\n");
txtReceiveData.AppendText(str2);
txtReceiveData.ScrollToCaret();
}
//下面用到了接收信息的代理功能,此为设计的要点之一
delegate void DelegateAcceptData();
void fun()
{
while (bAccpet)
{
AcceptData();
}
}
delegate void reaction();
void AcceptData()
{
if (txtReceiveData.InvokeRequired)
{
try
{
DelegateAcceptData ddd = new DelegateAcceptData(AcceptData);
this.Invoke(ddd, new object[] { });
}
catch { }
}
else
{
try
{
strRecieve = sp.ReadExisting();
txtReceiveData.AppendText(strRecieve);
}
catch (Exception ex) { }
}
}
private void bntClear_Click(object sender, EventArgs e)
{
txtReceiveData.Text = "";
}
private void button3_Click(object sender, EventArgs e)
{
try
{
string path = Directory.GetCurrentDirectory() + @"\output.txt";
string content = this.txtReceiveData.Text;
FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter write = new StreamWriter(fs);
write.Write(content);
write.Flush();
write.Close();
fs.Close();
MessageBox.Show("接收信息导出在:" + path);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}