查看文章
 
C#多线程编程---一个简单的聊天程序(Server)
2008-06-29 11:14
       这两天公司要求做一个聊天软件,要求基于Socket---TCP协议的。本人偷懒到网上一搜,好多阿!可后来仔细一看其实只有一个还算沾边。于是就下载下来,但是编译、运行都有问题。后来又找了好几个,都是一样的。估计就是大家你抄袭我的我抄袭他的,谁也没有真正的编译运行一下。结果看似挺好的软件,实际上根本不能运行。
       于是我用了一天的时间(其实没有这么多。)把它们整理了一下,基本上主要功能可以运行了。下面把它贴到网上供大家参考。

服务器端:

(1)Form1.cs[设计]界面
(2)Form1.cs[代码]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;

namespace ChatServer
{
    public partial class Form1 : Form
    {
        static int listenport = 8000;
        Socket clientsocket;
        Thread clientservice;
        ArrayList clients;
        Thread threadListen;
        TcpListener listener;
        delegate void AddListCallBack(string TextContext);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            clients = new ArrayList();
        }

        private void StartListening()
        {
            listener = new TcpListener(IPAddress.Parse("127.0.0.1"),listenport);
            listener.Start();
           
            while (true)
            {
                try
                {
                    Socket s = listener.AcceptSocket();
                    clientsocket = s;
                    clientservice = new Thread(new ThreadStart(ServiceClient));
                    clientservice.Start();

                    //MessageBox.Show(clientservice.ToString());
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
        }
        private void ServiceClient()
        {
            Socket client = clientsocket;
           
            bool keepalive = true;

            while (keepalive)
            {
                Byte[] buffer = new Byte[1024];
                client.Receive(buffer);
                string clientcommand = System.Text.Encoding.ASCII.GetString(buffer);


                string[] tokens = clientcommand.Split(new Char[]{'|'});
                Console.WriteLine(clientcommand);


                if (tokens[0] == "CONN")
                {
                    for (int n = 0; n < clients.Count; n++)
                    {
                        Client cl = (Client)clients[n];
                        SendToClient(cl, "JOIN|" + tokens[1]);
                    }
                    EndPoint ep = client.RemoteEndPoint;
                    Client c = new Client(tokens[1], ep, clientservice, client);
                    clients.Add(c);
                    string message = "LIST|" + GetChatterList() +"\r\n";
                    SendToClient(c, message);
                    AddList(c.ToString());
                    //listBox1.Items.Add(c);
                }

                if (tokens[0] == "CHAT")
                {
                    for (int n = 0; n < clients.Count; n++)
                    {
                        Client cl = (Client)clients[n];
                        SendToClient(cl, clientcommand);
                    }
                }
                if (tokens[0] == "PRIV")
                {
                    string destclient = tokens[2];
                    for(int n=0; n < clients.Count;n++)
                    {
                        Client cl = (Client)clients[n];
                        if(cl.Name.CompareTo(tokens[2]) == 0)
                                  SendToClient(cl, clientcommand);
                        // if(cl.Name.CompareTo(tokens[1]) == 0)
                        // SendToClient(cl, clientcommand);
                    }
                }
                if (tokens[0] == "GONE")
                {
                    int remove = 0;
                    bool found = false;
                    int c = clients.Count;
                    for (int n = 0; n < clients.Count; n++)
                    {
                        Client cl = (Client)clients[n];
                        SendToClient(cl, clientcommand);
                        if(cl.Name.CompareTo(tokens[1]) == 0)
                        {
                            remove = n;
                            found = true;
                            //listBox1.Items.Remove(cl);
                        }
                        //cl.CLThread.Abort();
                    }
                    if(found)
                        clients.RemoveAt(remove);
                    client.Close();
                    keepalive = false;
                }
            }
        }

        private void SendToClient(Client cl, string clientCommand)
        {
            Byte[] message = System.Text.Encoding.ASCII.GetBytes(clientCommand);
            Socket s = cl.Sock;
            if(s.Connected)
            {
                s.Send(message, message.Length, 0);
            }
        }

        private string GetChatterList()
        {
            string result = "";

            for (int i = 0; i < clients.Count; i++)
            {
                result += ((Client)clients[i]).Name + "|";
            }
            return result;
        }
       
        private void AddList(string textContext)
        {
            if (this.listBox1.InvokeRequired)
            {
                AddListCallBack d = new AddListCallBack(AddList);
                this.Invoke(d,new object[]{textContext});
            }
            else
            {
                this.listBox1.Items.Add(textContext);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            threadListen = new Thread(new ThreadStart(StartListening));
            threadListen.Start();
            label1.Text = "listening....";
        }

        private void button2_Click(object sender, EventArgs e)
        {
            listener.Stop();

            threadListen.Abort();
            threadListen.Join();
            label1.Text = "END....";
        }
    }
}

(3)Form1.Designer.cs
using System;

namespace ChatServer
{
    partial class Form1
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {

                if (clientservice != null)
                {
                    clientservice.Abort();
                }
                if (threadListen != null)
                {
                    try
                    {
                        threadListen.Abort();
                    }
                    catch (Exception ex)
                    {
                        threadListen = null;
                    }
                }

                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.listBox1 = new System.Windows.Forms.ListBox();
            this.button1 = new System.Windows.Forms.Button();
            this.label1 = new System.Windows.Forms.Label();
            this.button2 = new System.Windows.Forms.Button();
            this.SuspendLayout();
            //
            // listBox1
            //
            this.listBox1.FormattingEnabled = true;
            this.listBox1.ItemHeight = 12;
            this.listBox1.Location = new System.Drawing.Point(1, 3);
            this.listBox1.Name = "listBox1";
            this.listBox1.Size = new System.Drawing.Size(289, 220);
            this.listBox1.TabIndex = 0;
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(137, 229);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(68, 28);
            this.button1.TabIndex = 1;
            this.button1.Text = "START";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // label1
            //
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(12, 237);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(41, 12);
            this.label1.TabIndex = 2;
            this.label1.Text = "label1";
            //
            // button2
            //
            this.button2.Location = new System.Drawing.Point(211, 229);
            this.button2.Name = "button2";
            this.button2.Size = new System.Drawing.Size(70, 28);
            this.button2.TabIndex = 3;
            this.button2.Text = "END";
            this.button2.UseVisualStyleBackColor = true;
            this.button2.Click += new System.EventHandler(this.button2_Click);
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(293, 268);
            this.Controls.Add(this.button2);
            this.Controls.Add(this.label1);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.listBox1);
            this.Name = "Form1";
            this.Text = "聊天软件服务器";
            this.Load += new System.EventHandler(this.Form1_Load);
            this.ResumeLayout(false);
            this.PerformLayout();

        }

        #endregion

        private System.Windows.Forms.ListBox listBox1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Button button2;
    }
}

     (4)Client.cs Client Class
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace ChatServer
{
    using System.Net.Sockets;
    using System.Net;

    class Client
    {
        private Thread clthread;
        private EndPoint endpoint;
        private string name;
        private Socket sock;

        public Client(string _name, EndPoint _endpoint, Thread _thread, Socket _sock)
        {
            // TODO: 在此处添加构造函数逻辑
            clthread = _thread;
            endpoint = _endpoint;
            name = _name;
            sock = _sock;
        }

        public override string ToString()
        {
              return endpoint.ToString()+ " : " + name;
        }

        public Thread CLThread
        {
            get{return clthread;}
            set{clthread = value;}
        }

        public EndPoint Host
        {      
            get{return endpoint;}
            set{endpoint = value;}
        }

        public string Name
        {
            get{return name;}
            set{name = value;}
        }

        public Socket Sock
        {
            get{return sock;}
            set{sock = value;}
        }
   }
}


注:成员列表刷新有问题,没有解决。
       如果你还看到别的问题,请连同解决代码一起给我。我会及时更新的。
       Email:jobsmeng@QQ.com
       谢谢!!

类别:c#.net||添加到搜藏 |分享到i贴吧|浏览(2383)|评论 (0)
 
 
最近读者:
 
网友评论:
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
     

   
帮助中心 | 空间客服 | 投诉中心 | 空间协议
©2012 Baidu