本文参考《C#网络通信程序设计》(张晓明 编著)
程序界面如下图:

参数设置界面代码如下:
1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Windows.Forms; 9using System.IO.Ports; 10 11namespace ComDemo 12{ 13 public partial class ComSet : Form 14 { 15 public ComSet() 16 { 17 InitializeComponent(); 18 } 19 20 private void ComSet_Load(object sender, EventArgs e) 21 { 22 //串口 23 string[] ports = SerialPort.GetPortNames(); 24 foreach (string port in ports) 25 { 26 cmbPort.Items.Add(port); 27 } 28 cmbPort.SelectedIndex = 0; 29 30 //波特率 31 cmbBaudRate.Items.Add("110"); 32 cmbBaudRate.Items.Add("300"); 33 cmbBaudRate.Items.Add("1200"); 34 cmbBaudRate.Items.Add("2400"); 35 cmbBaudRate.Items.Add("4800"); 36 cmbBaudRate.Items.Add("9600"); 37 cmbBaudRate.Items.Add("19200"); 38 cmbBaudRate.Items.Add("38400"); 39 cmbBaudRate.Items.Add("57600"); 40 cmbBaudRate.Items.Add("115200"); 41 cmbBaudRate.Items.Add("230400"); 42 cmbBaudRate.Items.Add("460800"); 43 cmbBaudRate.Items.Add("921600"); 44 cmbBaudRate.SelectedIndex = 5; 45 46 //数据位 47 cmbDataBits.Items.Add("5"); 48 cmbDataBits.Items.Add("6"); 49 cmbDataBits.Items.Add("7"); 50 cmbDataBits.Items.Add("8"); 51 cmbDataBits.SelectedIndex = 3; 52 53 //停止位 54 cmbStopBit.Items.Add("1"); 55 cmbStopBit.SelectedIndex = 0; 56 57 //佼验位 58 cmbParity.Items.Add("无"); 59 cmbParity.SelectedIndex = 0; 60 } 61 62 private void bntOK_Click(object sender, EventArgs e) 63 { 64 //以下4个参数都是从窗体MainForm传入的 65 MainForm.strProtName = cmbPort.Text; 66 MainForm.strBaudRate = cmbBaudRate.Text; 67 MainForm.strDataBits = cmbDataBits.Text; 68 MainForm.strStopBits = cmbStopBit.Text; 69 DialogResult = DialogResult.OK; 70 } 71 72 private void bntCancel_Click(object sender, EventArgs e) 73 { 74 DialogResult = DialogResult.Cancel; 75 } 76 } 77}
主界面代码如下:
1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.Linq; 7using System.Text; 8using System.Windows.Forms; 9using System.IO.Ports; 10using System.IO; 11using System.Threading; 12 13namespace ComDemo 14{ 15 public partial class MainForm : Form 16 { 17 public MainForm() 18 { 19 InitializeComponent(); 20 } 21 private Thread getRecevice; 22 protected Boolean stop = false; 23 protected Boolean conState = false; 24 private StreamReader sRead; 25 string strRecieve; 26 bool bAccpet = false; 27 28 SerialPort sp = new SerialPort();//实例化串口通讯类 29 //以下定义4个公有变量,用于参数传递 30 public static string strProtName = ""; 31 public static string strBaudRate = ""; 32 public static string strDataBits = ""; 33 public static string strStopBits = ""; 34 35 private void MainForm_Load(object sender, EventArgs e) 36 { 37 groupBox1.Enabled = false; 38 groupBox2.Enabled = false; 39 this.toolStripStatusLabel1.Text = "端口号:端口未打开 | "; 40 this.toolStripStatusLabel2.Text = "波特率:端口未打开 | "; 41 this.toolStripStatusLabel3.Text = "数据位:端口未打开 | "; 42 this.toolStripStatusLabel4.Text = "停止位:端口未打开 | "; 43 this.toolStripStatusLabel5.Text = ""; 44 } 45 //串口设计 46 private void btnSetSP_Click(object sender, EventArgs e) 47 { 48 timer1.Enabled = false; 49 sp.Close(); 50 ComSet dlg = new ComSet(); 51 if (dlg.ShowDialog() == DialogResult.OK) 52 { 53 sp.PortName = strProtName;//串口号 54 sp.BaudRate = int.Parse(strBaudRate);//波特率 55 sp.DataBits = int.Parse(strDataBits);//数据位 56 sp.StopBits = (StopBits)int.Parse(strStopBits);//停止位 57 sp.ReadTimeout = 500;//读取数据的超时时间,引发ReadExisting异常 58 } 59 } 60 //打开/关闭串口 61 private void bntSwitchSP_Click(object sender, EventArgs e) 62 { 63 if (bntSwitchSP.Text == "打开串口") 64 { 65 if (strProtName != "" && strBaudRate != "" && strDataBits != "" && strStopBits != "") 66 { 67 try 68 { 69 if (sp.IsOpen) 70 { 71 sp.Close(); 72 sp.Open();//打开串口 73 } 74 else 75 { 76 sp.Open();//打开串口 77 } 78 bntSwitchSP.Text = "关闭串口"; 79 groupBox1.Enabled = true; 80 groupBox2.Enabled = true; 81 this.toolStripStatusLabel1.Text = "端口号:" + sp.PortName + " | "; 82 this.toolStripStatusLabel2.Text = "波特率:" + sp.BaudRate + " | "; 83 this.toolStripStatusLabel3.Text = "数据位:" + sp.DataBits + " | "; 84 this.toolStripStatusLabel4.Text = "停止位:" + sp.StopBits + " | "; 85 this.toolStripStatusLabel5.Text = ""; 86 87 } 88 catch (Exception ex) 89 { 90 MessageBox.Show("错误:" + ex.Message, "C#串口通信"); 91 } 92 } 93 else 94 { 95 MessageBox.Show("请先设置串口!", "RS232串口通信"); 96 } 97 } 98 else 99 { 100 timer1.Enabled = false; 101 timer2.Enabled = false; 102 bntSwitchSP.Text = "打开串口"; 103 if (sp.IsOpen) 104 sp.Close(); 105 groupBox1.Enabled = false; 106 groupBox2.Enabled = false; 107 this.toolStripStatusLabel1.Text = "端口号:端口未打开 | "; 108 this.toolStripStatusLabel2.Text = "波特率:端口未打开 | "; 109 this.toolStripStatusLabel3.Text = "数据位:端口未打开 | "; 110 this.toolStripStatusLabel4.Text = "停止位:端口未打开 | "; 111 this.toolStripStatusLabel5.Text = ""; 112 } 113 } 114 //发送数据 115 private void bntSendData_Click(object sender, EventArgs e) 116 { 117 if (sp.IsOpen) 118 { 119 try 120 { 121 sp.Encoding = System.Text.Encoding.GetEncoding("GB2312"); 122 sp.Write(txtSend.Text);//发送数据 123 } 124 catch (Exception ex) 125 { 126 MessageBox.Show("错误:" + ex.Message); 127 } 128 } 129 else 130 { 131 MessageBox.Show("请先打开串口!"); 132 } 133 } 134 //选择文件 135 private void btnOpenFile_Click(object sender, EventArgs e) 136 { 137 OpenFileDialog open = new OpenFileDialog(); 138 open.InitialDirectory = "c\\"; 139 open.RestoreDirectory = true; 140 open.FilterIndex = 1; 141 open.Filter = "txt文件(*.txt)|*.txt"; 142 if (open.ShowDialog() == DialogResult.OK) 143 { 144 try 145 { 146 if (open.OpenFile() != null) 147 { 148 txtFileName.Text = open.FileName; 149 } 150 } 151 catch (Exception err1) 152 { 153 MessageBox.Show("文件打开错误! " + err1.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Warning); 154 } 155 } 156 } 157 //发送文件内容 158 private void bntSendFile_Click(object sender, EventArgs e) 159 { 160 string fileName = txtFileName.Text.Trim(); 161 if (fileName == "") 162 { 163 MessageBox.Show("请选择要发送的文件!", "Error"); 164 return; 165 } 166 else 167 { 168 //sRead = new StreamReader(fileName); 169 sRead = new StreamReader(fileName,Encoding.Default);//解决中文乱码问题 170 } 171 timer1.Start(); 172 } 173 //发送文件时钟 174 private void timer1_Tick(object sender, EventArgs e) 175 { 176 string str1; 177 str1 = sRead.ReadLine(); 178 if (str1 == null) 179 { 180 timer1.Stop(); 181 sRead.Close(); 182 MessageBox.Show("文件发送成功!", "C#串口通讯"); 183 this.toolStripStatusLabel5.Text = ""; 184 return; 185 } 186 byte[] data = Encoding.Default.GetBytes(str1); 187 sp.Write(data, 0, data.Length); 188 this.toolStripStatusLabel5.Text = " 文件发送中..."; 189 } 190 //接收数据 191 private void btnReceiveData_Click(object sender, EventArgs e) 192 { 193 if (btnReceiveData.Text == "接收数据") 194 { 195 sp.Encoding = Encoding.GetEncoding("GB2312"); 196 if (sp.IsOpen) 197 { 198 //timer2.Enabled = true; //使用主线程进行 199 200 //使用委托以及多线程进行 201 bAccpet = true; 202 getRecevice = new Thread(new ThreadStart(testDelegate)); 203 //getRecevice.IsBackground = true; 204 getRecevice.Start(); 205 btnReceiveData.Text = "停止接收"; 206 } 207 else 208 { 209 MessageBox.Show("请先打开串口"); 210 } 211 } 212 else 213 { 214 //timer2.Enabled = false; 215 bAccpet = false; 216 try 217 { //停止主监听线程 218 if (null != getRecevice) 219 { 220 if (getRecevice.IsAlive) 221 { 222 if (!getRecevice.Join(100)) 223 { 224 //关闭线程 225 getRecevice.Abort(); 226 } 227 } 228 getRecevice = null; 229 } 230 } 231 catch { } 232 btnReceiveData.Text = "接收数据"; 233 } 234 } 235 private void testDelegate() 236 { 237 reaction r = new reaction(fun); 238 r(); 239 } 240 //用于接收数据的定时时钟 241 private void timer2_Tick(object sender, EventArgs e) 242 { 243 string str = sp.ReadExisting(); 244 string str2 = str.Replace("\r", "\r\n"); 245 txtReceiveData.AppendText(str2); 246 txtReceiveData.ScrollToCaret(); 247 } 248 //下面用到了接收信息的代理功能,此为设计的要点之一 249 delegate void DelegateAcceptData(); 250 void fun() 251 { 252 while (bAccpet) 253 { 254 AcceptData(); 255 } 256 } 257 258 delegate void reaction(); 259 void AcceptData() 260 { 261 if (txtReceiveData.InvokeRequired) 262 { 263 try 264 { 265 DelegateAcceptData ddd = new DelegateAcceptData(AcceptData); 266 this.Invoke(ddd, new object[] { }); 267 } 268 catch { } 269 } 270 else 271 { 272 try 273 { 274 strRecieve = sp.ReadExisting(); 275 txtReceiveData.AppendText(strRecieve); 276 } 277 catch (Exception ex) { } 278 } 279 } 280 281 private void bntClear_Click(object sender, EventArgs e) 282 { 283 txtReceiveData.Text = ""; 284 } 285 286 private void button3_Click(object sender, EventArgs e) 287 { 288 try 289 { 290 string path = Directory.GetCurrentDirectory() + @"\output.txt"; 291 string content = this.txtReceiveData.Text; 292 FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write); 293 StreamWriter write = new StreamWriter(fs); 294 write.Write(content); 295 write.Flush(); 296 write.Close(); 297 fs.Close(); 298 MessageBox.Show("接收信息导出在:" + path); 299 } 300 catch (Exception ex) 301 { 302 MessageBox.Show(ex.Message); 303 } 304 } 305 } 306}