前戏


【PS:原文手打,转载说明出处】

  【PS:博主自认为适用于云平台设备管控,且适用于IM主控】

  好久没来了,13年时还想着多写一些博客,这都17年过年,年前也写一写Scoket+多线程,不足之处,见谅。(算是个人小总结)

缘由


不知各位同仁有没有发现,用简单,无外乎就是都是一个流程

1)监听链接

  2)校验链接是否是正常链接

  3)保存链接至全局静态字典

  4)开启新线程监听监听到的线程报文

  5)执行对应命令或者发送对应命令

  然后内部各种心跳,各种断线重连后释放缘由链接对象,重新保存对象;

  其实使用过程当中,貌似也就这些来着,不管再大的系统,也都是这个主流程,但是一些细节处理如何把握;

  下面我简单的说说我的处理

  (1)分布式

  (2)线程在无命令状态下自我销毁

  (3)线程状态监听

  

正文


  1 分布式

    背景:其实吧,也算是我公司穷,用不起高大上的硬件负载,其次能由于个人学历水平有限,搞不定各种开源导致的以下产物

    1.1 流程图

      

    1.2 流程说明

      分布式服务器中植入程序

        1)负责监听前置机发送当前连接数以及服务资源使用情况

        2)监听客户机连接并返回当前最优前置至客户机

        3)客户机连接前置

  2 前置机处理

     当客户机连接至前置机时,前置机实时监听后,开始监听到底是哪一台客户机连接上来,在用Dictionary<key,Socket>存储连接Socket,开启新线程监听客户机心跳等

    关键:连接初始化指令时,带入客户机唯一标识,这时字典中存储的key为唯一标识,value为Socket

    2.1 前置与分布式服务器

        1:根据字典中保存的Socket,监听Socket最后链接时间,以及判断Socket链接状态,统计连接成功数据,释放连接中断Socket,发送连接数至分布式服务器

        2:发送当前前置程序内存、CPU占用百分比等相关服务器硬件使用情况信息至分布式服务器

     2.2 前置与客户机

      因为连接上了,不止只收取命令,还需要发送对应命令至客户机,顾沿用字典中存储的长连接Socket对象,发送命令至客户机

      因为是命令,遵循应答原则,必须命令到达后,返回明确指令收到,在发送下一条命令,这里我使用了线程阻塞(当然,如果是IM发送聊天记录就没关系了,集体丢到客户机就可以了,返回成功后在更新发送时间以及发送状态就好)

   3 编码

      流程大家应该其实都懂,然后就是代码,因为马上年终尾牙,要去粗饭了,代码贴上来,各自领悟领悟哈

      为什么要重写堆栈,以为我的是设备,设备命令必须保证命令一定送达,而且有顺序的执行,则重新写了个规则

      

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

namespace KR.DevFx.SocketTools
{
    public class DevQueue:IDisposable
    {
        #region 属性
        ;

        /// <summary>
        /// 序号
        /// </summary>
        public int No
        {
            get { return no; }
            set { no = value; }
        }

        ;

        /// <summary>
        /// 当前执行序号
        /// </summary>
        public int CurrentCommandNo
        {
            get { return currentCommandNo; }
            set { currentCommandNo = value; }
        }

        private bool queueSwitch = false;

        /// <summary>
        /// 堆栈开关
        /// </summary>
        public bool QueueSwitch
        {
            get { return queueSwitch; }
            set { queueSwitch = value; }
        }

        private bool isMeanwhileExec = false;

        /// <summary>
        /// 是否同时执行
        /// </summary>
        public bool IsMeanwhileExec
        {
            get { return isMeanwhileExec; }
            set { isMeanwhileExec = value; }
        }

        private Dictionary<int, object> dicCommand = new Dictionary<int, object>();

        /// <summary>
        /// 堆栈内容
        /// </summary>
        public Dictionary<int, object> DicCommand
        {
            get { return dicCommand; }
            set { dicCommand = value; }
        }

        #endregion

        #region 方法

        /// <summary>
        /// 参数入栈
        /// </summary>
        /// <param name="_param"></param>
        public void AddQueue(object _param)
        {
            if (No == int.MaxValue)
            {
                No = ;
            }
            No = No + ;
            DicCommand.Add(No, _param);
        }

        /// <summary>
        /// 取堆栈数据
        /// </summary>
        /// <returns></returns>
        public object GetQueue()
        {
            ;
            if (QueueSwitch)
            {
                throw new Exception("当前堆未执行结束,无法再次获取堆内内容!如需获取必须执行RemoveQueue方法");
            }

            if (DicCommand.ContainsKey(nextCommandNo))
            {
                if (!IsMeanwhileExec)
                    QueueSwitch = true;
                object returnVlaue = DicCommand[nextCommandNo];
                CurrentCommandNo = CurrentCommandNo + ;
                return returnVlaue;
            }
            return null;
        }

        /// <summary>
        /// 移出当前堆栈内容
        /// </summary>
        /// <returns></returns>
        public bool RemoveQueue()
        {
            )
            {
                if (DicCommand.ContainsKey(CurrentCommandNo))
                {
                    QueueSwitch = false;
                    return DicCommand.Remove(CurrentCommandNo);
                }
                else
                    throw new Exception(string.Format("根据当前命令号未找到堆栈内容!命令号:{0}", CurrentCommandNo));
            }
            else
            {
                QueueSwitch = false;
                return true;
            }
        }

        /// <summary>
        /// 移出当前堆栈内容,且获取下一堆栈内容对象
        /// </summary>
        /// <returns></returns>
        public object RemoveQueueAndGet()
        {
            if (RemoveQueue())
            {
                return GetQueue();
            }
            else
            {
                return null;
            }
        }

        #endregion

        public void Dispose()
        {
            No = ;
            CurrentCommandNo = ;
            DicCommand.Clear();
        }
    }
}

DevQueue 栈堆

      线程管控,为什么要重写,因为发现了在多线程过程中,使用线程状态来判断线程是否在执行还是死睡状态不准导致,具体原因没有刨根。

      

//*****************************************************************
// Description: 线程助手
// Author: HUAQIAN ZHOU
// Created Date: 2016/12/26
//*****************************************************************
// Modified By:
// Modification Date:
// Purpose of Modification:
//*****************************************************************

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

namespace KR.DevFx.SocketTools
{
    public class DevThreadPool
    {

        public static Dictionary<string, DevThread> DicLastingThread = new Dictionary<string, DevThread>();

    }

    /// <summary>
    /// 线程助手
    /// </summary>
    public class DevThread : IDisposable
    {
        #region 构造函数
        public DevThread()
        {
            ThreadStatus = DevThreadStatus.JustInit;
        }

        /// <summary>
        /// 初始化线程
        /// </summary>
        /// <param name="_threadPara"></param>
        /// <param name="_threadName"></param>
        /// <param name="isLasting"></param>
        public DevThread(string _threadName)
        {
            ThreadStatus = DevThreadStatus.JustInit;

            if (!DevThreadPool.DicLastingThread.ContainsKey(_threadName))
            {
                DevThreadPool.DicLastingThread.Add(_threadName, this);
            }
            ThreadName = _threadName;
        }

        #endregion

        #region 线程堆栈命令

        private DevQueue _threadQueue = new DevQueue();

        public DevQueue ThreadQueue
        {
            get { return _threadQueue; }
            set { _threadQueue = value; }
        }

        #endregion

        #region 属性

        /// <summary>
        /// 执行内容适用委托
        /// </summary>
        /// <param name="work"></param>
        public delegate void ThreadFunByPara(Object work);

        /// <summary>
        /// 线程工作的内容委托
        /// </summary>
        public ThreadFunByPara FunByPara { get; set; }

        /// <summary>
        /// 执行内容适用委托
        /// </summary>
        /// <param name="work"></param>
        public delegate void ThreadFun();

        /// <summary>
        /// 线程工作的内容委托
        /// </summary>
        public ThreadFun Fun { get; set; }

        private Thread _currentThread;

        /// <summary>
        /// 当前线程
        /// </summary>
        public Thread CurrentThread
        {
            get { return _currentThread; }
            set { _currentThread = value; }
        }

        private string threadStatus;

        /// <summary>
        /// 当前线程状态
        /// </summary>
        public string ThreadStatus
        {
            get { return threadStatus; }
            set { threadStatus = value; }
        }

        private object _threadPara;

        /// <summary>
        /// 线程参数
        /// </summary>
        public object ThreadPara
        {
            get { return _threadPara; }
            set { _threadPara = value; }
        }

        private string _threadName;

        /// <summary>
        /// 线程名称
        /// </summary>
        public string ThreadName
        {
            get { return _threadName; }
            set { _threadName = value; }
        }

        #endregion

        #region 方法
        /// <summary>
        /// 开启线程
        /// </summary>
        public void ThreadStart()
        {
            if (ThreadStatus == DevThreadStatus.JustInit)
            {
                CurrentThread = new Thread(new ThreadStart(Process));
                CurrentThread.IsBackground = true;
                ThreadStatus = KR.DevFx.SocketTools.DevThreadStatus.Running;
                CurrentThread.Start();
            }
            else if (ThreadStatus == DevThreadStatus.SleepWait)
            {
                CurrentThread.IsBackground = true;
                ThreadStatus = KR.DevFx.SocketTools.DevThreadStatus.Running;
                CurrentThread.Interrupt();
            }
            else if (CurrentThread.ThreadState == ThreadState.Stopped || ThreadStatus == DevThreadStatus.Abort)
            {
                CurrentThread = new Thread(new ThreadStart(Process));
                CurrentThread.IsBackground = true;
                ThreadStatus = KR.DevFx.SocketTools.DevThreadStatus.Running;
                CurrentThread.Start();
            }
        }

        /// <summary>
        /// 开启线程
        /// </summary>
        /// <param name="_objPara">线程参数</param>
        public void ThreadStart(object _objPara)
        {
            if (_objPara == null)
            {
                throw new Exception("exception:DevThread ThreadStart para is null");
            }
            if (ThreadStatus == DevThreadStatus.JustInit)
            {
                CurrentThread = new Thread(new ThreadStart(Process));
                CurrentThread.IsBackground = true;
                ThreadPara = _objPara;
                ThreadStatus = KR.DevFx.SocketTools.DevThreadStatus.Running;
                CurrentThread.Start();
            }
            else if (ThreadStatus == DevThreadStatus.SleepWait)
            {
                ThreadStatus = KR.DevFx.SocketTools.DevThreadStatus.Running;
                CurrentThread.IsBackground = true;
                ThreadPara = _objPara;
                CurrentThread.Interrupt();
            }
            else if (CurrentThread.ThreadState == ThreadState.Stopped || ThreadStatus == DevThreadStatus.Abort)
            {
                CurrentThread = new Thread(new ThreadStart(Process));
                CurrentThread.IsBackground = true;
                ThreadStatus = KR.DevFx.SocketTools.DevThreadStatus.Running;
                CurrentThread.Start();
            }
        }

        /// <summary>
        /// 线程处理方法(调用委托执行)
        /// </summary>
        private void Process()
        {
            try
            {
                if (ThreadPara == null)
                {
                    Fun();
                }
                else
                {
                    FunByPara(ThreadPara);
                }
            }
            catch
            {
            }
        }

        /// <summary>
        /// 睡眠时间
        /// </summary>
        /// <param name="timeout"></param>
        public void ThreadSleep(int timeout)
        {
            try
            {
                Thread.Sleep(timeout);
            }
            catch
            {
            }
        }

        /// <summary>
        /// 无限睡眠
        /// </summary>
        public void ThreadSleep()
        {
            try
            {
                ThreadStatus = DevThreadStatus.SleepWait;
                Thread.Sleep(Timeout.Infinite);
            }
            catch
            {
            }
        }

        /// <summary>
        /// 线程释放
        /// </summary>
        public void Dispose()
        {
            ThreadQueue.Dispose();
            try
            {
                if (CurrentThread != null)
                {
                    CurrentThread.Abort();
                    CurrentThread = null;
                }
            }
            catch
            {
            }
        }

        #endregion
    }

    /// <summary>
    /// 线程状态
    /// </summary>
    public class DevThreadStatus
    {
        /// <summary>
        /// 正在执行
        /// </summary>
        public const string Running = "Running";

        /// <summary>
        /// 线程等待
        /// </summary>
        public const string SleepWait = "SleepWait";

        /// <summary>
        /// 刚初始化
        /// </summary>
        public const string JustInit = "JustInit";

        /// <summary>
        /// 线程终止
        /// </summary>
        public const string Abort = "Abort";

    }

}

SocketTools

     线程阻塞

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

namespace KR.ClientServices.Service
{
    public class WaitResponseMessage
    {

        private string _WaitResopnseData = "";
        /// <summary>
        /// 要等待的响应报文数据
        /// </summary>
        public string WaitResopnseData
        {
            get { return _WaitResopnseData; }
            set { _WaitResopnseData = value; }
        }

        private string _WaitResponseDataCode = "";
        /// <summary>
        /// 要等待的响应报文标识码
        /// </summary>
        public string WaitResponseDataCode
        {
            get { return _WaitResponseDataCode; }
            set { _WaitResponseDataCode = value; }
        }
        ;

        /// <summary>
        /// 发送数据超时等待时间 秒
        /// </summary>
        public int SendDataWaitTimeOut
        {
            get { return _SendDataWaitTimeOut; }
            set { _SendDataWaitTimeOut = value; }
        }
        /// <summary>
        /// 发送数据超时阻塞器
        /// </summary>
        private ManualResetEvent SendDataObturator = new ManualResetEvent(false);
        /// <summary>
        /// 开始等待
        /// </summary>
        /// <returns></returns>
        public bool BeginWait()
        {
            SendDataObturator.Reset();
            return SendDataObturator.WaitOne(SendDataWaitTimeOut, false);
        }
        /// <summary>
        /// 结束等待
        /// </summary>
        public void EndWait()
        {
            SendDataObturator.Set();
        }
    }
}

WaitResponseMessage

    发送时处理

    

public SystemResult SendWait(byte[] sendData, string code)
        {
            lock (ApSocket)
            {
                SystemResult sr = new SystemResult();
                try
                {
                    WaitSendResponseMessage.WaitResponseDataCode = code;
                    this.ApSocket.Send(sendData);
                    if (WaitSendResponseMessage.BeginWait())
                    {
                        sr.ResultMsg = WaitSendResponseMessage.WaitResopnseData;
                        //应答    1    0x06:成功
                    }
                    else
                    {
                        sr.ResultMsg = "发送数据失败:响应超时";
                        sr.Status = ;
                    }
                }
                catch (Exception ex)
                {
                    sr.Status = ;
                    sr.ResultMsg = ex.Message;
                }
                return sr;
            }
        }

SendWait

结尾


就这样了哈,过个好年,我们公司是小公司,现在目前也没有说几十万几百万台设备在对外使用,所以也没测试贫瘠来着,希望那天我能面对几十万台,几百万台设备同时上来让我耍耍,那时候工资花啦啦的,哈哈哈

浅谈Socket长连+多线程[原创,欢迎指点]的更多相关文章

  1. 浅谈Socket长连+多线程

    缘由 不知各位同仁有没有发现,用简单,无外乎就是都是一个流程 1)监听链接 2)校验链接是否是正常链接 3)保存链接至全局静态字典 4)开启新线程监听监听到的线程报文 5)执行对应命令或者发送对应命令 ...

  2. 【转】浅谈多核CPU、多线程、多进程

    浅谈多核CPU.多线程.多进程 1.CPU发展趋势 核心数目依旧会越来越多,依据摩尔定律,由于单个核心性能提升有着严重的瓶颈问题,普通的桌面PC有望在2017年末2018年初达到24核心(或者16核3 ...

  3. 浅谈Session的使用(原创)

    目录 浅谈Session的使用(原创) 1.引言 2.Session域的生命周期 2.1 Session的创建 2.2 Session的销毁 3.那么,session被销毁后,其中存放的属性不就都访问 ...

  4. 浅谈Socket编程

    浅谈Socket编程 说到Socket,想必大家会觉得陌生又熟悉.许多同学听说过Socket,但仅仅知道它翻译成中文叫做套接字,除此之外似乎并没有太多的了解了.那么今天我就来抛砖引玉地聊一聊Socke ...

  5. (转)浅谈.NET下的多线程和并行计算(一)前言

    转载——原文地址:http://www.cnblogs.com/lovecindywang/archive/2009/12/25/1632014.html 作为一个ASP.NET开发人员,在之前的开发 ...

  6. 浅谈多核CPU、多线程、多进程

    1.CPU发展趋势 核心数目依旧会越来越多,依据摩尔定律,由于单个核心性能提升有着严重的瓶颈问题,普通的桌面PC有望在2017年末2018年初达到24核心(或者16核32线程),我们如何来面对这突如其 ...

  7. 浅谈 Boost.Asio 的多线程模型

    Boost.Asio 有两种支持多线程的方式,第一种方式比较简单:在多线程的场景下,每个线程都持有一个io_service,并且每个线程都调用各自的io_service的run()方法. 另一种支持多 ...

  8. <转>浅谈 Boost.Asio 的多线程模型

    本文转自:http://senlinzhan.github.io/2017/09/17/boost-asio/ Boost.Asio 有两种支持多线程的方式,第一种方式比较简单:在多线程的场景下,每个 ...

  9. 浅谈最长上升子序列(LIS)

    一.瞎扯的内容 给一个长度为n的序列,求它的最长上升子序列(LIS) 简单的dp n=read(); ;i<=n;i++) a[i]=read(); ;i<=n;i++) ;j<i; ...

随机推荐

  1. json转义字符串

    json前台写数据 @RequestMapping("/addUserJson") public void addUserJson(User user,HttpServletReq ...

  2. javascript中0.01*2324=23.240000000000002 ?

    js中的乘法运算的小问题 0.01*2324=23.240000000000002 ? , 结果为什么出现这么多小数位呢?

  3. 天天记录 - Android抓包 - 抓取HTTP,TCP协议数据

    需要两个工具tcpdump和Wireshark,  tcpdump的使用需要root权限     一  tcpdump   1. 下载 tcpdump首页  http://www.tcpdump.or ...

  4. FTP详解

    概述 FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文传协议”.用于Internet上的控制文件的双向传输.同时,它也是一个应用程序(Applicat ...

  5. Nginx 负载均衡 后端 监控检测 nginx_upstream_check_module 模块的使用

    在使用nginx 的负载均衡 中,我们通常会使用到 Nginx 自带的 ngx_http_proxy_module 健康检测模块. ngx_http_proxy_module 自带的 健康检测模块参数 ...

  6. OPENCV图像变换-1

    图像变换是指将一幅图像变换为图像数据的另一种表现形式,例如将图像进行傅立叶变换,或者对图像进行X,Y方向的求导等,经过这些变换,可以将图像数据处理中的某些问题换一个别的角度想办法,所以图像变换是图像处 ...

  7. CodeForces 622B The Time

    水题. #include <stdio.h> #include <algorithm> #include <string.h> #include <queue ...

  8. hellocharts-android开源图表库(效果非常好)

    泡在网上的日子 发表于 2014-11-07 12:28 第 33156 次阅读 chart 2 编辑推荐:稀土掘金,这是一个高质量的技术干货分享社区,web前端.Android.iOS.设计资源和产 ...

  9. ios-Ineligible Devices 不被识别的设备

    此问题大致分为几种: 1.设备不可用,出现Ineligible Devices,如下图: 此错误因为 Xcode的Deployment Target 大于设备的,选择和设备一样 或者 低于设备的.如下 ...

  10. uCOS-iii 中定义的一些常量

    uCOS-iii 中定义的一些常量 uCOS-iii 中有许多宏定义的量,这些量不需要全部记住是什么意思,因为在阅读代码的时候可以选中变量或宏定义然后右键查看定义,就可以知道它代表的什么意思.但是如果 ...