首页 > 编程语言 >C# Tcp Server端实现,使用TcpListener

C# Tcp Server端实现,使用TcpListener

时间:2024-08-16 16:53:36浏览次数:11  
标签:set get C# bytes Tcp cd client Server public

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using F.Studio.Common.Cfg;
using System.Collections.Concurrent;

namespace KomaxCSTcpServer
{
    public class AcquireServer : IDisposable
    {

        private object lockObj = new object();
        public String IP { get; private set; }
        public int Port { get; private set; } //7788
        public String Position { get; set; }
        public TcpListener _Listener = null;
        private bool IsRuning = false;
        private bool _Enabled = false;
        private bool disposed = false;
        public List<ClientDescription> _ClientList = new List<ClientDescription>();
        public event EventHandler<DataReceivedArgs> DataReceived = null;


        public AcquireServer(string ip, int port)
        {
            this.IP = ip;
            this.Port = port;
        }
        public void Start()
        {
            if (_Enabled) return;
            _Enabled = true;

            ThreadPool.QueueUserWorkItem((o) => { _Start(); });

        }
        private void _Start()
        {
            LogInfo("进入工作线程:" + Thread.CurrentThread.ManagedThreadId);
            while (IsRuning)
            {
                Thread.Sleep(1000 * 1);
            }


            try
            {
                _Listener = new TcpListener(IPAddress.Any, Port);
                _Listener.Start();

                // Enter the listening loop.
                while (_Enabled)
                {
                    Console.WriteLine("Waiting for a connection... ");

                    IsRuning = true;
                    // Perform a blocking call to accept requests.
                    // You could also use server.AcceptSocket() here.
                    TcpClient client = _Listener.AcceptTcpClient();
                    Console.WriteLine("Connected!");
                    ThreadPool.QueueUserWorkItem(o => { ReceptionClient(client); }, null);



                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }
            finally
            {
                if (_Listener != null)
                {
                    try
                    {
                        Console.WriteLine("关闭监听...");
                        _Listener.Stop();
                    }
                    catch { }
                }
                IsRuning = false;

                if (_Enabled)
                {

                    ThreadPool.QueueUserWorkItem((o) => { _Start(); });
                }

                LogInfo("退出工作线程:" + Thread.CurrentThread.ManagedThreadId);
            }






        }

        private void AddToList(ClientDescription client)
        {
            lock (lockObj)
            {
                if (_ClientList.Any(ent => ent.Equals(client))) return;


                _ClientList.Add(client);

            }
        }
        private void RemoveFromList(ClientDescription client)
        {
            lock (lockObj)
            {
                _ClientList.Remove(client);
            }
        }

        /// <summary>
        /// 发送给全部链接
        /// </summary>
        /// <param name="bytes"></param>
        public void SendToAllClient(byte[] bytes)
        {
            try
            {
                lock (lockObj)
                {
                    foreach (var cd in _ClientList)
                    {
                        if (!cd.IsDead)
                        {
                            cd._Queue4CmdBytes.Enqueue(bytes);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogErr(ex);
            }
        }
        /// <summary>
        /// 发送给最后接入链接
        /// </summary>
        /// <param name="bytes"></param>
        public void SendToLastConnClient(byte[] bytes)
        {

            try
            {

                var cd = _ClientList.OrderByDescending(ent => ent.ConnectedTime).FirstOrDefault();
                if (cd != null)
                {
                    if (!cd.IsDead)
                    {
                        cd._Queue4CmdBytes.Enqueue(bytes);
                    }
                }


            }
            catch (Exception ex)
            {
                LogErr(ex);
            }
        }
        private void ReceptionClient(TcpClient client)
        {
            #region 数据处理
            var cd = new ClientDescription(client);

            cd.RemotePoint = client.Client.RemoteEndPoint as IPEndPoint;
            cd.LocalPoint = client.Client.LocalEndPoint as IPEndPoint;
            cd.ConnectedTime = DateTime.Now;
            cd.LastInterchangeDataTime = DateTime.Now;

            AddToList(cd);

            Byte[] buffer = new byte[1024];
            int errCount = 0;

            var _Stream = client.GetStream();
           


            while (_Enabled && cd._Loop)
            {

                #region Poll
                try
                {

                    #region 数据发送处理

                    if (cd._Queue4CmdBytes.Count > 0)
                    {
                        byte[] bytes = null;
                        if (cd._Queue4CmdBytes.TryDequeue(out bytes))
                        {
                            if (_Stream != null)
                            {
                                _Stream.Write(bytes, 0, bytes.Length);
                                //发送成功更新最后交换时间
                                cd.LastInterchangeDataTime = DateTime.Now;
                                Thread.Sleep(50);
                            }
                        }
                    }


                    #endregion

                    #region 数据接收处理
                    if (_Stream.DataAvailable)
                    {
                        var len = _Stream.Read(buffer, 0, buffer.Length);
                        if (len <= 0) throw new Exception("收到零长度数据!");
                        if (len > 0) cd.LastInterchangeDataTime = DateTime.Now;
                        var bytes = new Byte[len];
                        Array.Copy(buffer, bytes, len);
                        var rawDataStr = Encoding.UTF8.GetString(buffer, 0, len);
                        LogInfo(rawDataStr);
                        if (DataReceived != null)
                        {
                            try
                            {
                                DataReceived(cd, new DataReceivedArgs() { Bytes = bytes, RawStr = rawDataStr,ClientDes=cd });
                            }
                            catch (Exception ex)
                            {
                                LogErr(ex);
                            }
                        }
                        //HandleReceiveStr(bytes, rawDataStr);
                        errCount = 0;
                    }
                    #endregion

                    #region 超时断开链接
                    var maxHoldSeconds = SimpleCfgMgr.GetV<int>("ConnMaxHoldSeconds", 120);
                    var checkConnUseHB = SimpleCfgMgr.GetV<bool>("CheckConnUseHB", true);
                    if ((DateTime.Now - cd.LastInterchangeDataTime).TotalSeconds > maxHoldSeconds)
                    {
                        if (checkConnUseHB)
                        {

                            var bytes_HB = Encoding.UTF8.GetBytes(string.Format("$HB:{0}$", DateTime.Now.Ticks));
                            cd.SendCmd(bytes_HB);

                        }
                        else
                        {
                            cd._Loop = false;
                        }

                    }
                    #endregion



                    Thread.Sleep(10);
                }
                catch (Exception ex)
                {
                    errCount++;
                    if (errCount >= 1)
                    {
                        cd._Loop = false;
                    }

                    LogErr(ex);
                    Thread.Sleep(1000 * 3);
                }
                finally
                {

                }
                #endregion
            }


            //标记成死链接
            cd.IsDead = true;
            #region 尝试关闭链接--这个会通知已经链接的客户端
            try { _Stream.Close(); }
            catch { }
            try { client.Close(); }
            catch { }
            #endregion

            RemoveFromList(cd);
            LogInfo(string.Format("断开与链接{0}:{1}的交互", cd.RemotePoint.Address, cd.RemotePoint.Port));
            #endregion
        }

        public void Stop()
        {
            _Enabled = false;
            if (_Listener != null)
            {

                try { _Listener.Stop(); }
                catch { }
            }

            while (IsRuning)
            {
                Thread.Sleep(1000 * 1);
            }
        }

        #region Log
        private void LogErr(Exception ex)
        {
            if (!SimpleCfgMgr.GetV<bool>("LogErr", true)) return;
            Console.WriteLine(string.Format("[{0}->{1}:{2}] Err:{3}", DateTime.Now.ToString("HH:mm:ss"), IP, Port, ex.Message));
        }

        private void LogInfo(string msg)
        {
            if (!SimpleCfgMgr.GetV<bool>("LogInfo", true)) return;
            Console.WriteLine(string.Format("[{0}->{1}:{2},T:{4}] Info:{3}", DateTime.Now.ToString("HH:mm:ss"), IP, Port, msg, Thread.CurrentThread.ManagedThreadId));
        }

        #endregion


        #region IDisposable Members

        /// <summary>
        /// Performs application-defined tasks associated with freeing, 
        /// releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Releases unmanaged and - optionally - managed resources
        /// </summary>
        /// <param name="disposing"><c>true</c> to release both managed 
        /// and unmanaged resources; <c>false</c> 
        /// to release only unmanaged resources.
        /// </param>
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    try
                    {
                        Stop();
                    }
                    catch
                    {

                    }
                }

                disposed = true;
            }
        }

        #endregion
    }

    public class DataReceivedArgs : EventArgs
    {
        public ClientDescription ClientDes { get; set; }
        public Byte[] Bytes { get; set; }
        public String RawStr { get; set; }
    }
    public class ClientDescription
    {
        public DateTime ConnectedTime { get; set; }
        public DateTime LastInterchangeDataTime { get; set; }

        public IPEndPoint RemotePoint { get; set; }
        public IPEndPoint LocalPoint { get; set; }
        public String ClientName { get; set; }
        public bool IsDead { get; set; }
        public TcpClient _Client { get; set; }
        public bool _Loop { get; set; }
        private NetworkStream _Stream { get; set; }

        public ConcurrentQueue<byte[]> _Queue4CmdBytes = new ConcurrentQueue<byte[]>();

        public ClientDescription(TcpClient client)
        {
            _Client = client;
            _Stream = client.GetStream();
            _Loop = true;
        }
        public void Close()
        {
            _Loop = false;

        }
        public void SendCmd(byte[] bytes)
        {
            if (!IsDead && _Client != null && _Client.Connected)
            {
                _Queue4CmdBytes.Enqueue(bytes);
            }
        }
    }
}
View Code

 

标签:set,get,C#,bytes,Tcp,cd,client,Server,public
From: https://www.cnblogs.com/wdfrog/p/18363222

相关文章

  • 【萌新学习C语言】如何根据qsort库函数,写一个能给任何类型排序的冒泡排序。
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、sqort函数1.1qsort函数定义1.2qsort如何使用函数使用1.2.1用qsort函数,将结构体类型的name进行排序1.2.2用qsort函数,将结构体类型的age进行排序二、整数型的冒泡排序2.1冒泡排序思想三.......
  • C++智能指针讨论
    一段有问题的代码。#include<iostream>intmain(){for(inti=0;i<10000000;i++){double*p=newdouble(1);}return0;}这里就有了内存泄漏。修改为下边的代码,是可以的,但是会比较占用CPU资源。#include<iostream>intmain()......
  • React 中执行的 DOM 操作
    新增/插入对于需要新增/插入的节点,React会对workInProgressfiber.flags执行按位或Placement的操作。表示该fiber节点需要执行插入的操作。执行插入的主要方法是commitPlacement。在该方法中会根据当前Fiber节点是否存在兄弟Fiber节点判断要调用哪种方法。如果......
  • mac环境docker配置&终端配置代理
    dockerdesktop配置国内镜像&设置代理用自己家里的mac一直拉取镜像失败,网上查了一堆,最终终于通过设置国内加速镜像和设置代理才终于搞好了。设置国内镜像加速地址: 设置代理配置:之前设置过,但是好像设置的不对,导致一直不可用。这里的两行HTTP和HTTPS,我理解是指当需要访问HTTP......
  • EasyCVR视频汇聚平台构建远程安防监控:5大亮点解析,助力安防无死角
    随着科技的飞速发展,远程安防监控系统已经成为现代社会中不可或缺的一部分,无论是在小区、公共场所还是工业领域,安防监控都发挥着至关重要的作用。而EasyCVR作为一款功能强大的视频监控综合管理平台,其在构建远程安防监控系统方面展现出了诸多显著优点。1、灵活部署与扩展性EasyCVR......
  • EasyCVR视频汇聚平台:打造全栈视频监控系统的基石,解锁可视化管理与高效运维
    随着科技的飞速发展,视频监控已成为现代社会不可或缺的一部分,广泛应用于社区、公共场所、工业领域等多个场景。EasyCVR视频汇聚平台,作为一款高性能的视频汇聚管理平台,凭借其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。本文将深入探讨EasyCVR视频......
  • docker配置文件daemon.json
    docker配置文件daemon.json1.配置文件的作用  1)可以配置下载的镜像源,即镜像加速器:常见的有配置阿里云镜像源,因为docker的官方镜像源下载镜像很慢  2)可以配置连接到不安全的私有仓库2.配置文件存放的路径  /etc/docker3.配置下载的镜像源地址和允许连接到不安全的私......
  • Clion控制台中文输出/报错信息乱码的最完美解决方案(无需更改注册表,beta版UTF-8)
    Clion控制台中文输出/报错信息乱码的最完美解决方案(无需更改注册表,beta版UTF-8)1.问题:clion控制台乱码2.错误解决方案:Ctrl+Shift+Alt+/,回车,打开注册表,取消勾选"run.processes.with.pty"(clion可能会卡死)3.正确方式:1.Ctrl+Alt+S打开设置2.找到编辑器Editor-文件编码Fil......
  • WebRTC为何成为视频开发领域的首选技术?
    随着互联网的飞速发展,视频通信已成为日常生活和工作中不可或缺的一部分。从在线教育、视频会议到远程医疗、在线直播,视频开发的需求日益增长。在这些应用场景中,选择何种技术来构建视频系统至关重要。目前,在很多视频业务的开发中,大家都热衷于选择使用WebRTC技术。WebRTC(WebReal-T......
  • JDK 17 以上 switch 语句的 变化
    在JDK17中,switch语句得到了显著的增强,引入了模式匹配(PatternMatching)等特性,使得代码更加简洁、高效。以下是JDK17中switch语句的主要用法和特点:1.格式变化在JDK17中,switch语句的格式发生了改变,主要体现在以下几个方面:冒号变为箭头:传统的switch语句中的冒号(:)在JDK17中被......