以前C/S通讯这一块都是基于套接字(Sockets)编程,但是面对业务逻辑复杂的C/S系统,通讯这一块往往都是被封装好了的,前几天写的一个小小窗体聊天程序,主要是练习一下C#封装的TcpListener、TcpClient以及NetworkStream的使用,直接看图上代码:
- using System;
- using System.Drawing;
- using System.Collections;
- using System.ComponentModel;
- using System.Windows.Forms;
- using System.Data;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.IO;
- namespace ChartTestServer
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- private NetworkStream networkStream;
- private StreamReader streamReader;
- private StreamWriter streamWriter;
- private Socket socketForClient;
- private TcpListener tcpListener;
- private Thread serverThread;// 启动服务线程
- private Thread recvThread;// 接收信息线程
- private void button1_Click(object sender, EventArgs e)
- {
- serverThread = new Thread(new ThreadStart(Listen));
- serverThread.Start();
- }
- //[STAThread]
- private void Listen()
- {
- try
- {
- Int32 port = Int32.Parse(txtPort.Text);
- IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
- tcpListener = new TcpListener(ipAddress, port);
- // 开始侦听
- tcpListener.Start();
- listBox1.Items.Add("服务已经启动!");
- button1.Enabled = false;
- button2.Enabled = true;
- // 返回可以用以处理连接的Socket实例
- socketForClient = tcpListener.AcceptSocket();
- // 如果返回值是"true",则产生的套节字已经接受来自远方的连接请求
- if (socketForClient.Connected)
- {
- button3.Enabled = true;
- listBox1.Items.Add("客户端成功连接上服务器!");
- // 创建networkStream对象通过网络套节字来接受和发送数据
- networkStream = new NetworkStream(socketForClient);
- // 从当前数据流中读取一行字符,返回值是字符串
- streamReader = new StreamReader(networkStream);
- streamWriter = new StreamWriter(networkStream);
- recvThread = new Thread(new ThreadStart(RecvData));
- recvThread.Start();
- }
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "Server提示");
- }
- }
- // 接收服务器发来的信息
- private void RecvData()
- {
- string msg = streamReader.ReadLine();
- // 如果不是接收到客户端发来的退出信息,则不断接收信息
- while (!msg.Equals("exit"))
- {
- //statusChart1.Value = Convert.ToInt32(msg);
- listBox1.Items.Add("收到信息: " + msg);
- msg = streamReader.ReadLine();
- }
- // 如果接收到客户的退出信息,则退出服务
- button1.Enabled = true;
- button2.Enabled = false;
- button3.Enabled = false;
- listBox1.Items.Add("客户已经关闭");
- listBox1.Items.Add("服务器关闭");
- // 关闭资源
- ReleaseResource();
- }
- private void button3_Click(object sender, EventArgs e)
- {
- Thread sendThread = new Thread(new ThreadStart(SendData));
- sendThread.Start();
- }
- private void SendData()
- {
- if (txtMsg.Text != "")
- {
- listBox1.Items.Add("发送信息: " + txtMsg.Text);
- // 往当前的数据流中写入一行字符串
- streamWriter.WriteLine(txtMsg.Text);
- // 刷新当前数据流中的数据
- streamWriter.Flush();
- txtMsg.Text = ""; // 清空
- }
- else
- {
- MessageBox.Show("发送信息不能为空","提示");
- }
- }
- private void button2_Click(object sender, EventArgs e)
- {
- try
- {
- if (button3.Enabled == true)
- {
- // 停止服务后,允许 启动服务,但是不允许发送消息
- button1.Enabled = true;
- button2.Enabled = false;
- button3.Enabled = false;
- string exitMsg = "exit"; // 要退出时,发送 exit 信息给客户端
- streamWriter.WriteLine(exitMsg);
- // 刷新当前数据流中的数据
- streamWriter.Flush();
- listBox1.Items.Add("服务器关闭");
- // 释放资源
- recvThread.Abort();
- ReleaseResource();
- }
- else
- {
- // 停止服务后,允许 启动服务,但是不允许发送消息
- button1.Enabled = true;
- button2.Enabled = false;
- button3.Enabled = false;
- listBox1.Items.Add("服务器关闭");
- // 关闭TCP连接,关闭线程
- tcpListener.Stop();
- serverThread.Abort();
- }
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "Server提示");
- }
- }
- // 释放资源
- private void ReleaseResource()
- {
- networkStream.Close();
- streamReader.Close();
- streamWriter.Close();
- socketForClient.Shutdown(SocketShutdown.Both);
- socketForClient.Close();
- tcpListener.Stop();
- }
- private void Form1_FormClosing(object sender, FormClosingEventArgs e)
- {
- // 在未停止 服务 前,不允许关闭窗体
- if (button1.Enabled == false)
- {
- MessageBox.Show("请先停止服务!", "Server提示");
- e.Cancel = true;
- }
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- // 在没有启动服务器之前,不允许停止服务以及发送信息
- button2.Enabled = false;
- button3.Enabled = false;
- }
- }
- using System;
- using System.Drawing;
- using System.Collections;
- using System.ComponentModel;
- using System.Windows.Forms;
- using System.Data;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.IO;
- namespace ChartTestServer
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- private NetworkStream networkStream;
- private StreamReader streamReader;
- private StreamWriter streamWriter;
- private Socket socketForClient;
- private TcpListener tcpListener;
- private Thread serverThread; // 启动服务线程
- private Thread recvThread;// 接收信息线程
- private void button1_Click(object sender, EventArgs e)
- {
- serverThread = new Thread(new ThreadStart(Listen));
- serverThread.Start();
- }
- //[STAThread]
- private void Listen()
- {
- try
- {
- Int32 port = Int32.Parse(txtPort.Text);
- IPAddress ipAddress = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
- tcpListener = new TcpListener(ipAddress, port);
- // 开始侦听
- tcpListener.Start();
- listBox1.Items.Add("服务已经启动!");
- button1.Enabled = false;
- button2.Enabled = true;
- // 返回可以用以处理连接的Socket实例
- socketForClient = tcpListener.AcceptSocket();
- // 如果返回值是"true",则产生的套节字已经接受来自远方的连接请求
- if (socketForClient.Connected)
- {
- button3.Enabled = true;
- listBox1.Items.Add("客户端成功连接上服务器!");
- // 创建networkStream对象通过网络套节字来接受和发送数据
- networkStream = new NetworkStream(socketForClient);
- // 从当前数据流中读取一行字符,返回值是字符串
- streamReader = new StreamReader(networkStream);
- streamWriter = new StreamWriter(networkStream);
- recvThread = new Thread(new ThreadStart(RecvData));
- recvThread.Start();
- }
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "Server提示");
- }
- }
- // 接收服务器发来的信息
- private void RecvData()
- {
- string msg = streamReader.ReadLine();
- // 如果不是接收到客户端发来的退出信息,则不断接收信息
- while (!msg.Equals("exit"))
- {
- //statusChart1.Value = Convert.ToInt32(msg);
- listBox1.Items.Add("收到信息: " + msg);
- msg = streamReader.ReadLine();
- }
- // 如果接收到客户的退出信息,则退出服务
- button1.Enabled = true;
- button2.Enabled = false;
- button3.Enabled = false;
- listBox1.Items.Add("客户已经关闭");
- listBox1.Items.Add("服务器关闭");
- // 关闭资源
- ReleaseResource();
- }
- private void button3_Click(object sender, EventArgs e)
- {
- Thread sendThread = new Thread(new ThreadStart(SendData));
- sendThread.Start();
- }
- private void SendData()
- {
- if (txtMsg.Text != "")
- {
- listBox1.Items.Add("发送信息: " + txtMsg.Text);
- // 往当前的数据流中写入一行字符串
- streamWriter.WriteLine(txtMsg.Text);
- // 刷新当前数据流中的数据
- streamWriter.Flush();
- txtMsg.Text = ""; // 清空
- }
- else
- {
- MessageBox.Show("发送信息不能为空", "提示");
- }
- }
- private void button2_Click(object sender, EventArgs e)
- {
- try
- {
- if (button3.Enabled == true)
- {
- // 停止服务后,允许 启动服务,但是不允许发送消息
- button1.Enabled = true;
- button2.Enabled = false;
- button3.Enabled = false;
- string exitMsg = "exit"; // 要退出时,发送 exit 信息给客户端
- streamWriter.WriteLine(exitMsg);
- // 刷新当前数据流中的数据
- streamWriter.Flush();
- listBox1.Items.Add("服务器关闭");
- // 释放资源
- recvThread.Abort();
- ReleaseResource();
- }
- else
- {
- // 停止服务后,允许 启动服务,但是不允许发送消息
- button1.Enabled = true;
- button2.Enabled = false;
- button3.Enabled = false;
- listBox1.Items.Add("服务器关闭");
- // 关闭TCP连接,关闭线程
- tcpListener.Stop();
- serverThread.Abort();
- }
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "Server提示");
- }
- }
- // 释放资源
- private void ReleaseResource()
- {
- networkStream.Close();
- streamReader.Close();
- streamWriter.Close();
- socketForClient.Shutdown(SocketShutdown.Both);
- socketForClient.Close();
- tcpListener.Stop();
- }
- private void Form1_FormClosing(object sender, FormClosingEventArgs e)
- {
- // 在未停止 服务 前,不允许关闭窗体
- if (button1.Enabled == false)
- {
- MessageBox.Show("请先停止服务!", "Server提示");
- e.Cancel = true;
- }
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- // 在没有启动服务器之前,不允许停止服务以及发送信息
- button2.Enabled = false;
- button3.Enabled = false;
- }
- }
![](https://img-my.csdn.net/uploads/201208/15/1345023186_5104.png)
- using System;
- using System.Drawing;
- using System.Collections;
- using System.ComponentModel;
- using System.Windows.Forms;
- using System.Data;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.IO;
- namespace ChartTest
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- private NetworkStream networkStream;
- private StreamReader streamReader;
- private StreamWriter streamWriter;
- private TcpClient myclient;
- private Thread recvThread; // 接收信息线程
- private Thread sendThread;// 发送信息线程
- private Thread serverThread;// 服务线程
- private Thread st;
- private void button1_Click(object sender, EventArgs e)
- {
- serverThread = new Thread(new ThreadStart(Connection));
- serverThread.Start();
- }
- private void Connection()
- {
- /*
- try
- {
- IPAddress ipAddress = IPAddress.Parse(txtIP.Text);
- Int32 port = Int32.Parse(txtPort.Text);
- IPEndPoint ipe = new IPEndPoint(ipAddress, port);
- myclient = new TcpClient();
- myclient.Connect(ipe);
- }
- catch
- {
- MessageBox.Show("没有连接到服务器!");
- return;
- }
- */
- try
- {
- IPAddress ipAddress = IPAddress.Parse(txtIP.Text);
- Int32 port = Int32.Parse(txtPort.Text);
- string hostName = Dns.GetHostEntry(ipAddress).HostName;
- myclient = new TcpClient(hostName, port);
- }
- catch
- {
- MessageBox.Show("没有连接到服务器!");
- return;
- }
- listBox1.Items.Add("客户端成功连接上服务器!");
- button1.Enabled = false; // 连接上了,不让按“连接”按钮
- button2.Enabled = true;
- button3.Enabled = true;
- networkStream = myclient.GetStream();
- streamReader = new StreamReader(networkStream);
- streamWriter = new StreamWriter(networkStream);
- // 创建接收信息线程,并启动
- recvThread = new Thread(new ThreadStart(RecvData));
- recvThread.Start();
- }
- // 接收数据
- private void RecvData()
- {
- string s = streamReader.ReadLine();
- // 如果没接到服务器退出的消息,则继续接收信息
- while (s!=null&&!s.Equals("exit"))
- {
- listBox1.Items.Add("收到信息:" + s);
- s = streamReader.ReadLine();
- }
- // 收到服务器退出的消息,释放资源
- listBox1.Items.Add("服务器关闭");
- listBox1.Items.Add("客户端关闭");
- button1.Enabled = true;
- button2.Enabled = false;
- button3.Enabled = false;
- // streamReader.Close();
- // streamWriter.Close();
- // networkStream.Close();
- // myclient.Close();
- ReleaseResouce();
- }
- private void button2_Click(object sender, EventArgs e)
- {
- button1.Enabled = true; // 按了停止之后,“连接”按钮可以用,“发送”不能用
- button2.Enabled = false;
- button3.Enabled = false;
- string exitMsg = "exit"; // 要退出时,发送 exit 信息给服务器
- streamWriter.WriteLine(exitMsg);
- //刷新当前数据流中的数据
- streamWriter.Flush();
- listBox1.Items.Add("客户端关闭");
- ReleaseResouce();
- }
- private void button3_Click(object sender, EventArgs e)
- {
- // 启动发送线程
- sendThread = new Thread(new ThreadStart(SendData));
- sendThread.Start();
- }
- // 发送数据
- private void SendData()
- {
- // 发送信息不允许为空
- if (txtMsg.Text == "")
- {
- MessageBox.Show("发送的信息不能为空!");
- txtMsg.Focus();
- return;
- }
- try
- {
- //往当前的数据流中写入一行字符串
- streamWriter.WriteLine(txtMsg.Text);
- //刷新当前数据流中的数据
- streamWriter.Flush();
- listBox1.Items.Add("发送信息:" + txtMsg.Text);
- txtMsg.Text = ""; // 清空
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "ClientClient提示");
- }
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- // 在未连接服务器前,不能发送信息和停止
- button2.Enabled = false;
- button3.Enabled = false;
- }
- // 释放资源
- private void ReleaseResouce()
- {
- networkStream.Close();
- streamReader.Close();
- streamWriter.Close();
- if (sendThread!=null&&sendThread.IsAlive)
- {
- sendThread.Abort();
- }
- if (recvThread.IsAlive)
- {
- recvThread.Abort();
- }
- if (serverThread.IsAlive)
- {
- serverThread.Abort();
- }
- myclient.Close();
- }
- private void Form1_FormClosing(object sender, FormClosingEventArgs e)
- {
- // 如果是在连接中,则不允许关闭窗口
- if (button1.Enabled == false)
- {
- MessageBox.Show("请先停止连接!","ClientClient提示");
- e.Cancel = true;
- }
- }
- private void button4_Click(object sender, EventArgs e)
- {
- // 启动发送线程
- st = new Thread(new ThreadStart(SeData));
- st.Start();
- }
- // 发送数据
- private void SeData()
- {
- Random r = new Random();
- for (int i = 0; i < 10000; i++)
- {
- Thread.Sleep(400);
- try
- {
- //往当前的数据流中写入一行字符串
- streamWriter.WriteLine(r.Next(80).ToString());
- //刷新当前数据流中的数据
- streamWriter.Flush();
- listBox1.Items.Add("发送信息:" + r.Next(80).ToString());
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "ClientClient提示");
- }
- }
- }
- private void button5_Click(object sender, EventArgs e)
- {
- st.Abort();
- }
- }
- }
- using System;
- using System.Drawing;
- using System.Collections;
- using System.ComponentModel;
- using System.Windows.Forms;
- using System.Data;
- using System.Net;
- using System.Net.Sockets;
- using System.Threading;
- using System.IO;
- namespace ChartTest
- {
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- private NetworkStream networkStream;
- private StreamReader streamReader;
- private StreamWriter streamWriter;
- private TcpClient myclient;
- private Thread recvThread; // 接收信息线程
- private Thread sendThread; // 发送信息线程
- private Thread serverThread;// 服务线程
- private Thread st;
- private void button1_Click(object sender, EventArgs e)
- {
- serverThread = new Thread(new ThreadStart(Connection));
- serverThread.Start();
- }
- private void Connection()
- {
- /*
- try
- {
- IPAddress ipAddress = IPAddress.Parse(txtIP.Text);
- Int32 port = Int32.Parse(txtPort.Text);
- IPEndPoint ipe = new IPEndPoint(ipAddress, port);
- myclient = new TcpClient();
- myclient.Connect(ipe);
- }
- catch
- {
- MessageBox.Show("没有连接到服务器!");
- return;
- }
- */
- try
- {
- IPAddress ipAddress = IPAddress.Parse(txtIP.Text);
- Int32 port = Int32.Parse(txtPort.Text);
- string hostName = Dns.GetHostEntry(ipAddress).HostName;
- myclient = new TcpClient(hostName, port);
- }
- catch
- {
- MessageBox.Show("没有连接到服务器!");
- return;
- }
- listBox1.Items.Add("客户端成功连接上服务器!");
- button1.Enabled = false; // 连接上了,不让按“连接”按钮
- button2.Enabled = true;
- button3.Enabled = true;
- networkStream = myclient.GetStream();
- streamReader = new StreamReader(networkStream);
- streamWriter = new StreamWriter(networkStream);
- // 创建接收信息线程,并启动
- recvThread = new Thread(new ThreadStart(RecvData));
- recvThread.Start();
- }
- // 接收数据
- private void RecvData()
- {
- string s = streamReader.ReadLine();
- // 如果没接到服务器退出的消息,则继续接收信息
- while (s!=null&&!s.Equals("exit"))
- {
- listBox1.Items.Add("收到信息:" + s);
- s = streamReader.ReadLine();
- }
- // 收到服务器退出的消息,释放资源
- listBox1.Items.Add("服务器关闭");
- listBox1.Items.Add("客户端关闭");
- button1.Enabled = true;
- button2.Enabled = false;
- button3.Enabled = false;
- // streamReader.Close();
- // streamWriter.Close();
- // networkStream.Close();
- // myclient.Close();
- ReleaseResouce();
- }
- private void button2_Click(object sender, EventArgs e)
- {
- button1.Enabled = true; // 按了停止之后,“连接”按钮可以用,“发送”不能用
- button2.Enabled = false;
- button3.Enabled = false;
- string exitMsg = "exit"; // 要退出时,发送 exit 信息给服务器
- streamWriter.WriteLine(exitMsg);
- //刷新当前数据流中的数据
- streamWriter.Flush();
- listBox1.Items.Add("客户端关闭");
- ReleaseResouce();
- }
- private void button3_Click(object sender, EventArgs e)
- {
- // 启动发送线程
- sendThread = new Thread(new ThreadStart(SendData));
- sendThread.Start();
- }
- // 发送数据
- private void SendData()
- {
- // 发送信息不允许为空
- if (txtMsg.Text == "")
- {
- MessageBox.Show("发送的信息不能为空!");
- txtMsg.Focus();
- return;
- }
- try
- {
- //往当前的数据流中写入一行字符串
- streamWriter.WriteLine(txtMsg.Text);
- //刷新当前数据流中的数据
- streamWriter.Flush();
- listBox1.Items.Add("发送信息:" + txtMsg.Text);
- txtMsg.Text = ""; // 清空
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "ClientClient提示");
- }
- }
- private void Form1_Load(object sender, EventArgs e)
- {
- // 在未连接服务器前,不能发送信息和停止
- button2.Enabled = false;
- button3.Enabled = false;
- }
- // 释放资源
- private void ReleaseResouce()
- {
- networkStream.Close();
- streamReader.Close();
- streamWriter.Close();
- if (sendThread!=null&&sendThread.IsAlive)
- {
- sendThread.Abort();
- }
- if (recvThread.IsAlive)
- {
- recvThread.Abort();
- }
- if (serverThread.IsAlive)
- {
- serverThread.Abort();
- }
- myclient.Close();
- }
- private void Form1_FormClosing(object sender, FormClosingEventArgs e)
- {
- // 如果是在连接中,则不允许关闭窗口
- if (button1.Enabled == false)
- {
- MessageBox.Show("请先停止连接!", "ClientClient提示");
- e.Cancel = true;
- }
- }
- private void button4_Click(object sender, EventArgs e)
- {
- // 启动发送线程
- st = new Thread(new ThreadStart(SeData));
- st.Start();
- }
- // 发送数据
- private void SeData()
- {
- Random r = new Random();
- for (int i = 0; i < 10000; i++)
- {
- Thread.Sleep(400);
- try
- {
- //往当前的数据流中写入一行字符串
- streamWriter.WriteLine(r.Next(80).ToString());
- //刷新当前数据流中的数据
- streamWriter.Flush();
- listBox1.Items.Add("发送信息:" + r.Next(80).ToString());
- }
- catch (Exception exc)
- {
- MessageBox.Show(exc.Message, "ClientClient提示");
- }
- }
- }
- private void button5_Click(object sender, EventArgs e)
- {
- st.Abort();
- }
- }
- }
在Program.cs的Main()函数中加入下行代码可以解决关于线程访问控件问题,或者在窗体加载程序里使用这行代码
- System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls =false;
转自:http://blog.csdn.net/henuhaigang/article/details/8160196