`
mmdev
  • 浏览: 12889722 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

C#简单窗体聊天程序

 
阅读更多

以前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 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://download.csdn.net/detail/wangqiuyun/4502341

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics