C# TCP多线程服务器

封装好的类,直接上代码:

using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace YxSocketService
{
    /// <summary>
    /// 定义Socket服务类
    /// socketService = new YxSocketService(port);
    ///socketService.OnSocketReceive += SocketRecive;
    /// private void SocketRecive(string ipAndPort, byte[] data)
    /// {
    /// var s = System.Text.Encoding.Default.GetString(data);
    /// Console.WriteLine(ipAndPort + "=>" + s);
    /// }
    /// </summary>
    public class YxSocketService
    {
        public delegate void SocketReceiveHandler(string ipAndPort, byte[] datas);

        private Thread _threadWatch = null; // 负责监听客户端连接请求的 线程;
        private System.Net.Sockets.Socket _socketWatch = null;
        private Dictionary<string, System.Net.Sockets.Socket> _dict = new Dictionary<string, System.Net.Sockets.Socket>();//存放套接字
        private Dictionary<string, Thread> _dictThread = new Dictionary<string, Thread>();//存放线程

        public SocketReceiveHandler OnSocketReceive;

        public YxSocketService(int port)
        {
            // 创建负责监听的套接字,注意其中的参数;
            _socketWatch = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            // 获得文本框中的IP对象;
            IPAddress address = IPAddress.Any; // .Parse("10.10.16.185");
            // 创建包含ip和端口号的网络节点对象;
            IPEndPoint endPoint = new IPEndPoint(address, port);
            try
            {
                // 将负责监听的套接字绑定到唯一的ip和端口上;
                _socketWatch.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                _socketWatch.Bind(endPoint);
            }
            catch (SocketException ex)
            {
                YxLog.YxLog.Error(this.GetType(), ex);
                return;
            }
            // 设置监听队列的长度;
            _socketWatch.Listen(10000);
            // 创建负责监听的线程;
            _threadWatch = new Thread(WatchConnecting);
            _threadWatch.IsBackground = true;
            _threadWatch.Start();

            YxLog.YxLog.Info("服务器启动监听成功=>" + endPoint);
        }

        public void Send(string ipAndPort, string msg)
        {
            try
            {            
            System.Net.Sockets.Socket sokConnection = _dict[ipAndPort];
            if (sokConnection == null) return;

            byte[] data = System.Text.Encoding.Default.GetBytes(msg);
            sokConnection.Send(data);
            }
            catch (Exception ex)
            {
                YxLog.YxLog.Error(ex);
                //throw;
            }
        }

        /// <summary>
        /// 监听客户端请求的方法;
        /// </summary>
        private void WatchConnecting()
        {
            while (true)  // 持续不断的监听客户端的连接请求;
            {
                // 开始监听客户端连接请求,Accept方法会阻断当前的线程;
                System.Net.Sockets.Socket sokConnection = _socketWatch.Accept(); // 一旦监听到一个客户端的请求,就返回一个与该客户端通信的 套接字;

                YxLog.YxLog.Info("新客户端连接成功=>" + sokConnection.RemoteEndPoint);

                // 将与客户端连接的 套接字 对象添加到集合中;
                _dict.Add(sokConnection.RemoteEndPoint.ToString(), sokConnection);
                Thread thr = new Thread(RecMsg);
                thr.IsBackground = true;
                thr.Start(sokConnection);
                _dictThread.Add(sokConnection.RemoteEndPoint.ToString(), thr);  //  将新建的线程 添加 到线程的集合中去。
            }
        }

        void RecMsg(object sokConnectionparn)
        {
            System.Net.Sockets.Socket sokClient = sokConnectionparn as System.Net.Sockets.Socket;
            while (true)
            {
                // 定义一个缓存区;
                byte[] arrMsgRec = new byte[1024];
                // 将接受到的数据存入到输入  arrMsgRec中;
                int length = -1;
                try
                {
                    length = sokClient.Receive(arrMsgRec); // 接收数据,并返回数据的长度;
                    if (length > 0)
                    {
                        byte[] data = new byte[length];
                        Array.Copy(arrMsgRec, data, length);

                        //var s = YxFunctionHelper.ByteArrToHex(data); //如果是十六进制
                        var s = System.Text.Encoding.Default.GetString(data); //如果不是十六进制
                        YxLog.YxLog.Info(sokClient.RemoteEndPoint + " " + s);
                        //主业务

                        //执行回调事件
                        if (OnSocketReceive != null)
                        {
                            OnSocketReceive(sokClient.RemoteEndPoint.ToString(), data);
                        }                        

                    }
                    else
                    {
                        // 从 通信套接字 集合中删除被中断连接的通信套接字;
                        _dict.Remove(sokClient.RemoteEndPoint.ToString());
                        // 从通信线程集合中删除被中断连接的通信线程对象;
                        _dictThread.Remove(sokClient.RemoteEndPoint.ToString());

                        YxLog.YxLog.Info("" + sokClient.RemoteEndPoint + "断开连接");
                        //log.log("遇见异常"+se.Message);
                        break;
                    }
                }
                catch (SocketException se)
                {
                    // 从 通信套接字 集合中删除被中断连接的通信套接字;
                    _dict.Remove(sokClient.RemoteEndPoint.ToString());
                    // 从通信线程集合中删除被中断连接的通信线程对象;
                    _dictThread.Remove(sokClient.RemoteEndPoint.ToString());

                    YxLog.YxLog.Error("" + sokClient.RemoteEndPoint + "断开,异常消息:" + se.Message);
                    //log.log("遇见异常"+se.Message);
                    break;
                }
                catch (Exception e)
                {
                    // 从 通信套接字 集合中删除被中断连接的通信套接字;
                    _dict.Remove(sokClient.RemoteEndPoint.ToString());
                    // 从通信线程集合中删除被中断连接的通信线程对象;
                    _dictThread.Remove(sokClient.RemoteEndPoint.ToString());

                    YxLog.YxLog.Error(this.GetType(), e);
                    // log.log("遇见异常" + e.Message);
                    break;
                }
            }
        }
    }
}

 

posted @ 2018-01-03 10:22  都是城市惹的祸  阅读(448)  评论(0)    收藏  举报