Socket原理及代码(服务器端,自记录)


1.创建Socket对象

public Socket Socket
        {
            get;
            private set;
        }

2.绑定监听端口-Bind

public bool Start(string ipString, int port)
        {
            IPAddress address = null;
            IPAddress.TryParse(ipString, out address);
            if (address == null)
            {
                Loggers.Logger.Info("IP地址格式不正确!" + ipString);
                return false;
            }
            else
            {
                this.Bind(new IPEndPoint(address, port));
                return this.Start(); //函数体在3.监听           
            }
        }
 private void Bind(EndPoint local)
        {
            try
            {
                this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this.Socket.Bind(local);
            }
            catch (Exception ex)
            {
                Loggers.Logger.Info(ex.Message);
                return;
            }

        }

3.监听-Listen

public bool Start()
        {
            if (this.Socket == null)
            {
                Loggers.Logger.Error("Socket对象不能为空!");
                return false;
            }
            try
            {
                //监听队列
                this.Backlog = 10;
                this.Socket.Listen(this.Backlog);
                Loggers.Logger.Info("启动服务成功!" + this.Socket.LocalEndPoint.ToString());
                this.State = true;
                //循环接收客户端连接,启动线程池!
                ThreadPool.QueueUserWorkItem(new WaitCallback(Accept));
       
                this._SysTimer = new System.Timers.Timer();
                this._SysTimer.Interval = 30 * 60 * 1000;
                this._SysTimer.Elapsed += SysTimer_Elapsed;
                this._SysTimer.Start();

                return true;
            }
            catch (Exception ex)
            {
                Loggers.Logger.Error("启动服务异常:" + ex.ToString());
                return false;
            }
        }

4.循环等待客户端连接-Accpet (注意:开线程池 ↑)

public void Accept(object args)
        {
            while (this.State && this.Socket != null)
            {
                try
                {
                    Socket client = this.Socket.Accept();
                    lock (this._dicSessions)
                    {
                        string key = client.RemoteEndPoint.ToString();//Guid.NewGuid().ToString();
                        if (this._dicSessions.ContainsKey(key) == false)
                        {
                            SocketSession session = new SocketSession(key, client);
                            //接收信息处理函数
                            session.ReceiveEncoding = this.ReceiveEncoding;
                            session.RemoteClose += Session_RemoteClose;
                            session.ReceiveData += Session_ReceiveData;
                            this._dicSessions.Add(key, session);
                            if (this.RemoteConnect != null)
                                this.RemoteConnect(key);
                            //开始接收数据
                            session.StartReceive();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Loggers.Logger.Error("接收客户端异常:" + ex.ToString());
                }
            }
        }

程序参考(仅包含服务端Bind、 Listen、 Accept相关代码,接收Receive代码请参考下面的代码)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


namespace SMS_YBS.IOCPSockets
{
    //从 Start(string ipString, int port) 函数开始调用
    /// <summary>
    /// Tcp Server
    /// </summary>
    public class TcpSocketServer : IDisposable
    {
        public Socket Socket
        {
            get;
            private set;
        }
        public int Backlog
        {
            get; set;
        }
        public bool State
        {
            get;
            private set;
        }
        /// <summary>
        /// 本地服务器
        /// </summary>
        public EndPoint Local
        {
            get;
            private set;
        }   
        /// <summary>
        /// 接收数据编码格式
        /// </summary>
        public Encoding ReceiveEncoding
        {
            get; set;
        }
        /// <summary>
        /// 远程数据
        /// </summary>
        public event OnRemoteConnectHanlder RemoteConnect = null;
        /// <summary>
        /// 接收数据
        /// </summary>
        public event OnReceiveDataHanlder ReceiveData = null;
        
        /// <summary>
      	/// 关闭远程
    	/// </summary>
   	    public event OnRemoteCloseHanlder RemoteClose = null;//public event 委托 事件;

        private Dictionary<string, SocketSession> _dicSessions = new Dictionary<string, SocketSession>();
        /// <summary>
        /// 获取连接对象
        /// </summary>
        public Dictionary<string, SocketSession> Sessions
        {
            get { return new Dictionary<string, SocketSession>(this._dicSessions); }
        }
        private System.Timers.Timer _SysTimer = null;
        private BackgroundWorker _Worker = null;
        private DateTime _RunTime = DateTime.Now;
        
        /// <summary>
        /// 绑定地址-
        /// </summary>
        /// <param name="local"></param>
        private void Bind(EndPoint local)
        {
            try
            {
                this.Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                this.Socket.Bind(local);
            }
            catch (Exception ex)
            {
                Loggers.Logger.Info(ex.Message);
                return;
            }

        }

        #region 开始绑定接收连接
        /// <summary>
        /// 开始绑定接收连接
        /// </summary>
        /// <param name="ipString"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public bool Start(string ipString, int port)
        {
            IPAddress address = null;
            IPAddress.TryParse(ipString, out address);
            if (address == null)
            {
                Loggers.Logger.Info("IP地址格式不正确!" + ipString);
                return false;
            }
            else
            {
                this.Bind(new IPEndPoint(address, port));//IP和端口的整合称为终结点endpoint
                return this.Start();
               
            }
        }
        /// <summary>
        /// 开始绑定接收连接
        /// </summary>
        /// <param name="local"></param>
        /// <returns></returns>
        //public bool Start(EndPoint local)
        //{
        //    this.Bind(local);

        //    return this.Start();
        //}
        /// <summary>
        /// 开始绑定接收连接
        /// </summary>
        /// <returns></returns>
        public bool Start()
        {
            if (this.Socket == null)
            {
                Loggers.Logger.Error("Socket对象不能为空!");
                return false;
            }
            try
            {
                this.Backlog = 10;
                this.Socket.Listen(this.Backlog);
                Loggers.Logger.Info("启动服务成功!" + this.Socket.LocalEndPoint.ToString());
                this.State = true;

                ThreadPool.QueueUserWorkItem(new WaitCallback(Accept));
                //
                this._SysTimer = new System.Timers.Timer();
                this._SysTimer.Interval = 30 * 60 * 1000;//30分钟检查一次
                this._SysTimer.Elapsed += SysTimer_Elapsed;
                this._SysTimer.Start();

                return true;
            }
            catch (Exception ex)
            {
                Loggers.Logger.Error("启动服务异常:" + ex.ToString());
                return false;
            }
        }

        private void SysTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            if (this._Worker != null && this._Worker.IsBusy)
            {
                Loggers.Logger.Info("检查线程正在运行!");
                TimeSpan timeSpan = DateTime.Now - this._RunTime;
                if (timeSpan.TotalMinutes < 60)
                    return;

                Loggers.Logger.Info("检查线程超:" + timeSpan.TotalMinutes + "运行中,需要停止重新启动...");
                this.CheckClient();
            }
        }

        private void CheckClient()
        {
            this._RunTime = DateTime.Now;
            string[] keys = this._dicSessions.Keys.ToArray();
            foreach (var item in keys)
            {
                try
                {
                    int result = this._dicSessions[item].GetState();
                    Loggers.Logger.Info("返回结果:" + result);
                }
                catch (Exception ex)
                {
                    Loggers.Logger.Error("获取状态异常:" + ex.ToString());
                    this._dicSessions.Remove(item);
                }
            }
        }

        public void Accept(object args)
        {
            while (this.State && this.Socket != null)
            {
                try
                {
                    Socket client = this.Socket.Accept();
                    lock (this._dicSessions)
                    {
                        string key = client.RemoteEndPoint.ToString();//Guid.NewGuid().ToString();
                        if (this._dicSessions.ContainsKey(key) == false)
                        {
                            SocketSession session = new SocketSession(key, client);
                            session.ReceiveEncoding = this.ReceiveEncoding;
                            session.RemoteClose += Session_RemoteClose;
                            session.ReceiveData += Session_ReceiveData;
                            this._dicSessions.Add(key, session);
                            if (this.RemoteConnect != null)
                                this.RemoteConnect(key);

                            //开始接收数据
                            session.StartReceive();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Loggers.Logger.Error("接收客户端异常:" + ex.ToString());
                }
            }
        }

        private void Session_ReceiveData(IPEndPoint remote, byte[] buffer, int count)
        {
            if (this.ReceiveData != null)
                this.ReceiveData(remote, buffer, count);
        }

        private void Session_RemoteClose(string key)
        {
            if (this._dicSessions.ContainsKey(key))
                this._dicSessions.Remove(key);

            if (this.RemoteClose != null)
                this.RemoteClose(key);
        }
        #endregion

        #region 向远程客户端发送信息
        /// <summary>
        /// 向远程客户端发送信息
        /// </summary>
        /// <param name="ipString"></param>
        /// <param name="port"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public int SendTo(string key, byte[] data)
        {
            if (this._dicSessions.ContainsKey(key) == false)
            {
                Loggers.Logger.Info("未能找到远程连接:" + key);
                return -1;
            }
            var session = this._dicSessions[key];
            return session.Send(data);
        }
        /// <summary>
        /// 向远程客户端发送信息
        /// </summary>
        /// <param name="ipString"></param>
        /// <param name="port"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public int SendTo(SocketSession session, byte[] data)
        {
            return session.Send(data);
        }
        /// <summary>
        /// 向远程客户端发送信息
        /// </summary>
        /// <param name="remote"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public Dictionary<string, string> SendTo(byte[] data)
        {
            Dictionary<string, string> list = new Dictionary<string, string>();
            if (this._dicSessions.Count <= 0)
            {
                Loggers.Logger.Info("未能找到远程连接!");
                return list;
            }
            bool success = true;
            string[] keys = this._dicSessions.Keys.ToArray();
            foreach (var item in keys)
            {
                try
                {
                    this._dicSessions[item].Send(data);
                }
                catch (Exception ex)
                {
                    success = false;
                    Loggers.Logger.Error("发送数据异常:" + ex.ToString());
                    this._dicSessions.Remove(item);//移除发送失败的远程连接
                }
            }
            //存在发送失败的远程
            if (success == false)
            {
                if (this.RemoteClose != null)
                    this.RemoteClose(null);
            }
            return list;
        }

        /// <summary>
        /// 向远程客户端发送信息
        /// </summary>
        /// <param name="remote"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public Task<int> SendToAsync(string key, byte[] data)
        {
            return new Task<int>(() => this.SendTo(key, data));
        }
        /// <summary>
        /// 向远程客户端发送信息
        /// </summary>
        /// <param name="remote"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public Task<Dictionary<string, string>> SendToAsync(byte[] data)
        {
            return Task.Factory.StartNew<Dictionary<string, string>>(() => {
                return this.SendTo(data);
            });
        }


        #endregion
        /// <summary>
        /// 停止监听
        /// </summary>
        public void Close()
        {
            this.ClientClose();

            if (this.Socket != null)
            {
                //由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
                //this.Socket.Disconnect(true);

                this.Socket.Close(3);
                this.Socket.Dispose();
                this.Socket = null;
            }
        }

        private void ClientClose()
        {
            string[] keys = this._dicSessions.Keys.ToArray();
            foreach (var item in keys)
            {
                try
                {
                    Loggers.Logger.Info("开始关闭:" + this._dicSessions[item].Client.RemoteEndPoint.ToString() + "...");
                    this._dicSessions[item].Close();
                    this._dicSessions.Remove(item);
                    Loggers.Logger.Info("关闭成功");
                }
                catch (Exception ex)
                {
                    Loggers.Logger.Error("关闭异常:" + ex.ToString());
                    this._dicSessions.Remove(item);
                }
            }
        }
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            this.Close();
        }
    }
}

5.接收客户端的消息-Receive (注意:开线程池 ,循环接收)

 public bool StartReceive()
        {
            if (this.Client == null)
            {
                Loggers.Logger.Error("远程对象不能为空!");
                return false;
            }
            try
            {
                this.State = true;
                ThreadPool.QueueUserWorkItem(new WaitCallback(ReceiveThread));
                Loggers.Logger.Info(this.Client.LocalEndPoint.ToString() + "启动接收数据成功!");
                return true;
            }
            catch (Exception ex)
            {
                Loggers.Logger.Error("服务端启动异常:" + ex.ToString());
                return false;
            }
        }
    
private void ReceiveThread(object state)
        {
            while (this.State && this.Client != null && this.Client.Connected)
            {
                try
                {
                    byte[] mBuffer = new byte[10 * 1024];
                    int count = 0;
                    if (this.Client.Poll(-1, SelectMode.SelectRead))
                    {
                        count = this.Client.Receive(mBuffer);
                        if (count <= 0)
                        {
                            //连接已断开
                            this.Close();
                            return;
                        }
                    }
                        if (this.ReceiveEncoding == null)
                        this.ReceiveEncoding = System.Text.Encoding.UTF8;
                    //引发事件
                    if (this.ReceiveData != null)
                        this.ReceiveData((IPEndPoint)this.Client.RemoteEndPoint, mBuffer, count);
                }
                catch (Exception ex)
                {
                    //this.State = false;
                    Loggers.Logger.Error("接收数据异常:" + this.Client.RemoteEndPoint + ex.ToString());
                    this.Close();
                    return;
                }
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值