关闭

C# Socket多线程编程(一)

标签: 多线程socketc#stringexception
4546人阅读 评论(6) 收藏 举报
分类:
//实现服务器端

//创建Client类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ChartServer
{
    /// <summary>
    /// 客户端连接
    /// </summary>
    class Client
    {
        #region 字段
        //客户端连接线程
        private System.Threading.Thread clthread;
        //客户端连接网络地址
        private System.Net.EndPoint endpoint;
        //客户端名称
        private string name;
        //客户端对象
        private System.Net.Sockets.Socket sock;
        #endregion
        #region 构造
        //构造一个客户端连接
        public Client(string _name, System.Net.EndPoint _endpoint, System.Threading.Thread _thread, System.Net.Sockets.Socket _sock)
        {
            clthread = _thread;
            endpoint = _endpoint;
            name = _name;
            sock = _sock;
        }
        #endregion
        #region 方法
        //重写ToString方法
        public override string ToString()
        {
            //返回客户端连接网络地址和客户端连接名称
            return endpoint.ToString() + ":" + name;
        }
        #endregion
        #region 属性
        public System.Threading.Thread CLThread
        {
            get { return clthread; }
            set { clthread = value; }
        }
        public System.Net.EndPoint Host
        {
            get { return endpoint; }
            set { endpoint = value; }
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public System.Net.Sockets.Socket Sock
        {
            get { return sock; }
            set { sock = value; }
        }
        #endregion
    }
}

//服务器端代码

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;

namespace ChartServer
{
    public partial class ServerMain : Form
    {
        public ServerMain()
        {
            InitializeComponent();
        }

        //客户端连接
        System.Net.Sockets.Socket clientsocket;
        //连接集合
        System.Collections.ArrayList clients;
        //客户端线程
        System.Threading.Thread clientservice;
        System.Threading.Thread threadListen;
        System.Net.Sockets.TcpListener listener;
        System.Net.IPAddress ipAddress;
        Int32 listenport;
        public delegate void MyInvoke(string str);
        /// <summary>
        /// 开始侦听,允许客户端连接
        /// </summary>
        private void StartListening()
        {
            //定义网络连接侦听
            listener = new System.Net.Sockets.TcpListener(ipAddress,listenport);

            listener.Start();
            while (true)
            {
                try
                {
                    //开始侦听网络连接                    
                    clientsocket = listener.AcceptSocket();
                    //客户端连接线程
                    clientservice = new System.Threading.Thread(new System.Threading.ThreadStart(ServiceClient));
                    //启动线程
                    clientservice.Start();
                }
                catch (Exception e)
                {
                    MessageBox.Show("listening Error:" + e.Message);
                }
            }
        }
        private void ServiceClient()
        {
            //获取一个客户端连接
            System.Net.Sockets.Socket client = clientsocket;
            //定义一个是否存活的变量
            bool keepalive = true;
            //判断新连接是否存在
            if (client == null) keepalive = false;
            else keepalive = true;
            //判断客户端是否还存在
            while (keepalive)
            {
                //定义字节
                Byte[] buffer = new Byte[1024];
                //定义数据量
                int bufLen = 0;
                try
                {
                    //从客户端接收到的数据量
                    bufLen = client.Available;
                    //接收客户端发过来的数据
                    client.Receive(buffer, 0, bufLen, System.Net.Sockets.SocketFlags.None);
                    //假如客户端没有传入数据,则返回
                    if (bufLen == 0) continue;

                    //将字节转换为字符串
                    string clientcommand = System.Text.Encoding.ASCII.GetString(buffer).Substring(0, bufLen);
                    //分割从客户端传入的字符串
                    string[] tokens = clientcommand.Split(new Char[] { '|' });
                    //输出到控制台
                    Console.WriteLine(clientcommand);
                    //CONN:表示新建连接。发送格式:CONN|发送者名称
                    if (tokens[0] == "CONN")
                    {
                        //循环所有的客户端
                        for (int n = 0; n < clients.Count; n++)
                        {
                            //循环获取连接对象
                            Client cl = (Client)clients[n];
                            //向所有客户端发送新添加连接消息
                            SendToClient(cl, "JOIN|" + tokens[1]);
                        }
                        //获取新添加连接的网络地址
                        System.Net.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);
                        //创建线程 将新连接添加到当前连接集合中,使用匿名委托调用添加方法
                        System.Threading.Thread handlerControl = new System.Threading.Thread(delegate() { handlerListBox(c.Name + "|" + c.Host.ToString(), "add"); });
                        //启动线程
                        handlerControl.Start();
                    }
                    //CHAT:发送全局消息,所有其他连接都可以接收到。发送格式:CHAT|发送者名称|信息内容
                    if (tokens[0] == "CHAT")
                    {
                        //循环连接集合
                        for (int n = 0; n < clients.Count; n++)
                        {
                            //获取当前连接
                            Client cl = (Client)clients[n];
                            //发送消息
                            SendToClient(cl, clientcommand);
                        }
                    }
                    //PRIV:发送私聊信息。发送格式:PRIV|发送者名称|信息内容|接受者名称
                    if (tokens[0] == "PRIV")
                    {
                        //获取接受者连接名称
                        string destclient = tokens[3];
                        //循环集合列表
                        for (int n = 0; n < clients.Count; n++)
                        {
                            //获取连接
                            Client cl = (Client)clients[n];
                            //如果是接受者
                            if (cl.Name.CompareTo(tokens[3]) == 0)
                                //发送消息
                                SendToClient(cl, clientcommand);
                            //如果是发送者
                            if (cl.Name.CompareTo(tokens[1]) == 0)
                                //发送消息
                                SendToClient(cl, clientcommand);
                        }
                    }
                    //GONE 退出。发送格式:GONE|发送者名称
                    if (tokens[0] == "GONE")
                    {
                        //连接索引
                        int remove = 0;
                        //是否存在
                        bool found = false;
                        //当前连接数
                        int c = clients.Count;
                        //连接名称
                        string clientname = "";
                        //遍历集合
                        for (int n = 0; n < clients.Count; n++)
                        {
                            //获取连接
                            Client cl = (Client)clients[n];
                            //如果不是要退出的连接
                            if (cl.Name.CompareTo(tokens[1]) != 0)
                                //发送消息
                                SendToClient(cl, clientcommand);
                            else
                            {
                                //发送确认退出信息
                                SendToClient(cl, "QUIT|");
                                //获取连接名称
                                clientname = cl.Name + "|" + cl.Host.ToString();
                                //获取连接索引
                                remove = n;
                                //连接存在
                                found = true;
                            }
                        }
                        //连接存在
                        if (found)
                        {
                            //创建删除连接线程,从列表中删除连接
                            System.Threading.Thread t = new System.Threading.Thread(delegate() { handlerListBox( clientname, "del"); });
                            //启动线程
                            t.Start();
                            //从集合中删除连接
                            clients.RemoveAt(remove);
                            //改变存活状态
                            keepalive = false;
                        }
                    }
                }
                catch (Exception e)
                {
                    MessageBox.Show("Receive Error:" + e.Message);
                    keepalive = false;
                }
            }
        }
        /// <summary>
        /// 获取当前连接集合
        /// </summary>
        /// <returns></returns>
        private string GetChatterList()
        {
            string result = "";
            //循环集合,获取连接名称。
            for (int i = 0; i < clients.Count; i++)
            {
                //使用“|”分隔
                result += ((Client)clients[i]).Name + "|";
            }
            return result;
        }
        /// <summary>
        /// 发送信息到客户端
        /// </summary>
        /// <param name="cl">客户端连接</param>
        /// <param name="clientCommand">要发送的信息</param>
        private void SendToClient(Client cl, string clientCommand)
        {
            //将字符串转换成字节
            Byte[] message = System.Text.Encoding.ASCII.GetBytes(clientCommand);
            //获取连接对象
            System.Net.Sockets.Socket s = cl.Sock;
            //判断是否还在连接状态
            if (s.Connected)
            {
                //发送消息
                s.Send(message, message.Length, 0);
            }
        }
        /// <summary>
        /// 加载窗体类
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ServerMain_Load(object sender, EventArgs e)
        {
            //创建连接集合
            clients = new System.Collections.ArrayList();
        }
        /// <summary>
        /// 监听按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStartListening_Click(object sender, EventArgs e)
        {
            this.btnStartListening.Enabled = false;
            //获取服务器端IP地址
            ipAddress = System.Net.IPAddress.Parse("192.168.104.110");
            //获取服务器端口号
            listenport = 6666;
            //创建监听线程
            threadListen = new System.Threading.Thread(StartListening);
            //启动线程
            threadListen.Start();
            //创建设置状态文本线程
            System.Threading.Thread handlerControl = new System.Threading.Thread( delegate() { SetText("Listening..."); });
            //启动线程
            handlerControl.Start();
        }
        /// <summary>
        /// 设置连接文本
        /// </summary>
        /// <param name="s"></param>
        private void SetText(string s)
        {
            //判断是否是本线程调用
            if (lblMessage.InvokeRequired)
            {
                //如果不是,则使用委托,改变为本线程调用
                MyInvoke _myInvoke = new MyInvoke(SetText);
                //执行委托,传入参数
                this.Invoke(_myInvoke, new object[] { s });
            }
            else
            {
                //改变文本值
                this.lblMessage.Text = s;
            }
        }

        private void handlerListBox(string c, string o)
        {
            //判断是否是本线程调用
            if (lbClients.InvokeRequired)
            {
                //创建委托
                MyInvoke _myInvoke;
                //要执行的操作
                if (o == "add")
                    _myInvoke = new MyInvoke(addItem);
                else
                    _myInvoke = new MyInvoke(delItem);
                //执行委托,将参数传入
                this.Invoke(_myInvoke, new object[] { c });
            }
        }
        /// <summary>
        /// 在当前连接列表中删除一个连接
        /// </summary>
        /// <param name="c"></param>
        private void delItem(string c)
        {
            this.lbClients.Items.Remove(c);
        }
        /// <summary>
        /// 在当前连接列表中新建一个连接
        /// </summary>
        /// <param name="c"></param>
        private void addItem(string c)
        {
            this.lbClients.Items.Add(c);
        }
    }
}


    下载地址:示例代码下载


1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:332936次
    • 积分:3567
    • 等级:
    • 排名:第9566名
    • 原创:38篇
    • 转载:87篇
    • 译文:0篇
    • 评论:20条
    文章分类
    最新评论