⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smgsocketpool.cs

📁 联通的SGIP发送代码
💻 CS
字号:
/* jll(2005)版权所有,保留所有权力
 * 文件名:SMGSocketPool.cs
 * 用  途:这个文件包含一个SMGSocketPool的类,这个类建立socket缓冲池负责将二级sp发送的命令转发到服务器,
 *         又将服务器的应答转发到二级sp
 * 作  者:jll
 * 完成日期:2005年8月2日
 * 修订记录:
 */
using System;
using System.Collections.Generic;
using System.Text;

using System.Net;
using System.Net.Sockets;

namespace JLL.SGIP
{
    public class SMGSocketPool
    {
        private List<Socket> _buffer;
        private List<Socket> _using;
        private int _lessSocketCount = 0; //缺少的socket的个数, 如果缺少的socket到达某一数量,则应该考虑重新申请socket

        private IPAddress _serverIP;
        private int _serverPort;
        private int _maxSocketConnection;
        private string _userName;
        private string _passWord;

        internal int _answerTimeOut; //命令应答的最大间隔,毫秒

        internal SMGSocketPool()
        {
            _serverIP = SgipConfig.Server.IP;
            _serverPort = SgipConfig.Server.Port;
            _maxSocketConnection = SgipConfig.Server.MaxConnection;
            _userName = SgipConfig.SP.UserName;
            _passWord = SgipConfig.SP.Password;
            _answerTimeOut = SgipConfig.System.AnswerTimeOut * 1000;

            _buffer = new List<Socket>(_maxSocketConnection);
            _using = new List<Socket>(_maxSocketConnection);

            new System.Threading.Timer(new System.Threading.TimerCallback(CreateSocketPool), null, 0, 65000);
        }

        /// <summary>
        /// 向服务器发起一个连接,如果成功就将该Socket放入缓冲池中
        /// </summary>
        private void CreateASocket(object state)
        {
            Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                s.Connect(_serverIP, _serverPort);
                //向服务器(联通smg)发送bind命令,登录
                Bind bindBody = new Bind();
                bindBody.LoginName = _userName;
                bindBody.LoginPassword = _passWord;
                bindBody.LoginType = 1;
                Command cmd = Command.CreateCommand(bindBody);
                s.Send(cmd.GetBytes());
                //接收应答
                byte[] buff = new byte[1024];
                s.ReceiveTimeout = _answerTimeOut;
                s.Receive(buff);
                cmd = Command.ToCommand(buff, 0);
                if (((Bind_Resp)cmd.Body).Result == 0)
                {
                    //已向服务器建立起了一个连接, 放于缓冲池中
                    lock (_buffer)
                    {
                        _buffer.Add(s);
                    }
                }
            }
            catch
            {
                SgipHelper.ShutdownAndCloseSocket(s);
            }
        }

        /// <summary>
        /// 如果socket被关闭了, 就从缓冲池中移除,并返回true, 否则返回false
        /// </summary>
        /// <param name="s"></param>
        private bool RemoveIfDisconnected(Socket s)
        {
            if (!SgipHelper.IsSocketConnected(s))
            {
                SgipHelper.ShutdownAndCloseSocket(s);

                lock (_buffer)
                {
                    _buffer.Remove(s);
                }
                return true;
            }
            return false;
        }

        /// <summary>
        /// 建立起尽量多的socket连接放至缓冲池中
        /// </summary>
        private void PoolBufferSocket()
        {
            int nCount = _maxSocketConnection - _buffer.Count - _using.Count;

            for (int i = 0; i < nCount; ++i)
            {
                CreateASocket(null);
            }
        }

        /// <summary>
        /// 检查缓冲池中每一个socket的连接状态,如果断开了,则从缓冲池中移除
        /// </summary>
        private void CheckBufferSocket()
        {
            lock (_buffer)
            {
                int nCount = _buffer.Count;
                for (int i = 0; i < nCount; ++i)
                {
                    RemoveIfDisconnected(_buffer[i]);
                }
            }
        }

        /// <summary>
        /// 定期检查缓冲池中的socket是否有效,无效则移除并向服务器建立尽可能多的连接
        /// </summary>
        /// <param name="state"></param>
        private void CreateSocketPool(object state)
        {
            CheckBufferSocket();
            PoolBufferSocket();
        }

        /// <summary>
        /// 回收一个socket到缓冲池中
        /// </summary>
        /// <param name="s"></param>
        public void CollectSocket(Socket s)
        {
            lock (this)
            {
                _using.Remove(s);
                _buffer.Add(s);
            }
            if (RemoveIfDisconnected(s))
            {
                System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(CreateASocket));
            }
        }

         /// <summary>
        /// 从池中返回一个socket, 如果池中没有可用的socket, 则返回null
        /// </summary>
        /// <returns></returns>
        public Socket ReuqestSocket()
        {
            Socket result = null;
            lock (this)
            {
                if (_buffer.Count > 0)
                {
                    _lessSocketCount = 0;
                    result = _buffer[0];
                    _buffer.Remove(result);
                    _using.Add(result);
                }
                else
                {
                    _lessSocketCount++;
                }
                //重构缓冲池
                if ((_lessSocketCount >= _maxSocketConnection) || (_buffer.Count + _using.Count == 0))
                {
                    System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(CreateSocketPool));
                }
            }

            if (result == null)
            {
                return null;
            }
            //如果连接中断
            if (!SgipHelper.IsSocketConnected(result))
            {
                CollectSocket(result);
                lock (_buffer)
                {
                    return (_buffer.Count > 0) ? ReuqestSocket() : null;
                }
            }
            //清空socket的接收缓冲区
            try
            {
                int nAvailable = result.Available;
                if (nAvailable > 0)
                {
                    byte[] buffer = new byte[nAvailable];
                    result.Receive(buffer);
                }
            }
            catch
            {
            }
            return result;
        }



        private static SMGSocketPool _smgSocketPool = null;

        /// <summary>
        /// 建立起联通smg的socket缓冲池, 必须先调用这个方法才能用 ClientSendSubmit()和 ClientSendTrace()
        /// </summary>
        public static void BuildSocketPool()
        {
            if (_smgSocketPool == null)
            {
                _smgSocketPool = new SMGSocketPool();
            }
        }

        /// <summary>
        /// 二级sp发送一个Submit命令到联通smg
        /// </summary>
        /// <param name="client"></param>
        /// <param name="cmd"></param>
        public static void ClientSendSubmit(Socket client, Command submitCommand)
        {
            Socket socketSMG = _smgSocketPool.ReuqestSocket();

            if (socketSMG == null)
            {
                return;
            }

            try
            {
                //将submit的一些sp设置设为本机信息
                Submit body = (Submit)submitCommand.Body;
                body.CorpID = SgipConfig.SP.CorpID;
                //body.SPNumber = SgipConfig.SP.SPNumber;

                socketSMG.Send(submitCommand.GetBytes());
                socketSMG.ReceiveTimeout = _smgSocketPool._answerTimeOut;
                byte[] buffer = new byte[SgipConfig.MaxBufferCount];
                int nRead = socketSMG.Receive(buffer);
                //
                //这里做一些命令发送成功之后的处理,如:记录到数据库
                //
                client.Send(buffer, 0, nRead, SocketFlags.None);
            }
            catch
            {
            }
            finally
            {
                _smgSocketPool.CollectSocket(socketSMG);
            }
        }

        /// <summary>
        /// 二级sp发送一个Trace命令到联通smg
        /// </summary>
        /// <param name="client"></param>
        /// <param name="traceCommand"></param>
        public static void ClientSendTrace(Socket client, Command traceCommand)
        {
            Socket socketSMG = _smgSocketPool.ReuqestSocket();

            if (socketSMG == null)
            {
                return;
            }

            try
            {
                socketSMG.Send(traceCommand.GetBytes());
                socketSMG.ReceiveTimeout = 300000;//Trace应答最多5分钟
                byte[] buffer = new byte[SgipConfig.MaxBufferCount];
                socketSMG.Receive(buffer);
                Command cmdAnswer = Command.ToCommand(buffer, 0);
                client.Send(cmdAnswer.GetBytes());
            }
            catch
            {
            }
            finally
            {
                _smgSocketPool.CollectSocket(socketSMG);
            }
        }


    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -