using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Fleck;
namespace DB
{

	/// <summary>
	/// 客户端网络状态
	/// </summary>
	///
	public enum NetStateEnum
	{
		[Description("已连接")]
		Connected = 1,
		[Description("已发送")]
		SendData = 2,
		[Description("已接收")]
		ReceiveData = 3,
		[Description("已解析")]
		ParseData = 4,
		[Description("已离线")]
		Disconnected = 5,
		[Description("上报超时")]
		ReportTimeout = 6
	}

	/// <summary>
	/// 记录每一个Socket连接
	/// </summary>
	public class SocketConnectionInfo
	{
		private const int SocketDataBufferSize = 1024;//如果单包数据字节数大于该值则需要加大此值,以免分包

		/// <summary>
		/// 构造函数将一个套接字和一个客户号码
		/// </summary>
		/// <param name="socket">套接字</param>
		/// <param name="connectionId">设备唯一号</param>
		internal SocketConnectionInfo(IWebSocketConnection socket, string connectionId)
		{
			ConnectionId = connectionId;
			CurrentSocket = socket;
			DataBuffer = new byte[SocketDataBufferSize];
		}
		/// <summary>
		/// 析构函数
		/// </summary>
		~SocketConnectionInfo()
		{
			DataBuffer = null;
			CurrentSocket = null;
		}

		public void Close()
		{
			if (CurrentSocket != null/* && CurrentSocket.Connected*/)
			{
				CurrentSocket.Close();
			}
		}

		/// <summary>
		/// 客户端的套接字
		/// </summary>
		public IWebSocketConnection CurrentSocket { get; set; }

		/// <summary>
		/// 由客户机发送缓冲区来存储数据
		/// </summary>
		public byte[] DataBuffer { get; set; }

		/// <summary>
		/// 当前实际接收的数据字节数,与属性DataBuffer结合使用以确定实际接收的数据
		/// </summary>
		///
		public int DataBufferLen { get; set; }

		/// <summary>
		/// 数据接收时的系统时间
		/// </summary>
		public DateTime ReceivedTimeFromServer { get; set; }

		/// <summary>
		/// 最后一次接收的数据里的采集时间
		/// </summary>
		///
		public DateTime ReceivedTimeFromClient { get; set; }

		/// <summary>
		/// 是否在线
		/// </summary>
		public bool IsAlive
		{
			get
			{
				if (CurrentSocket != null)
				{
					return CurrentSocket.IsAvailable;
				}
				else
				{
					return false;
				}
			}

		}

		/// <summary>
		/// 用于标识socket连接
		/// </summary>
		public string ConnectionId { get; set; }

		public NetStateEnum NetDataState { get; set; }

		public byte[] LastUnParsedBytes { get; set; } // 缓存上次未解析的数据 缓存在每个连接中

		public object ParsedEntity { get; set; }

		/// <summary>
		/// 是否禁用,由用户手工更改。禁用后的连接不处理其收发数据,收到数据直接抛弃。防止客户端数据高频发送无效数据。
		/// </summary>
		public bool IsDisabled { get; set; }

		public bool IsLoggedIn { get; set; } //是否登录成功,只有登录成功的情况下才可以后续通信交互
											 /// <summary>
											 /// 当前使用的终端编号,每次通信都有可能修改
											 /// </summary>
		public string CurrentPileCode { get; set; }
		public string DeviceId { get; set; }

		public string TemporaryHint { get; set; }
		public string MessageTypeName { get; internal set; }
	}

	public class SocketConnectionInfoFactory
	{
		/// <summary>
		/// 所有客户端Socket连接的集合,通过socket对象索引
		/// </summary>
		private ConcurrentDictionary<IWebSocketConnection, SocketConnectionInfo> dictionary = new ConcurrentDictionary<IWebSocketConnection, SocketConnectionInfo>();

		public ConcurrentDictionary<IWebSocketConnection, SocketConnectionInfo> GetItems()
		{
			return dictionary;
		}
		public SocketConnectionInfo BindSocketConnectionInfo(IWebSocketConnection socket, string connectionId)
		{
			SocketConnectionInfo socketConnectionInfo;
			if (dictionary.ContainsKey(socket))
			{
				socketConnectionInfo = dictionary[socket];
			}
			else
			{
				socketConnectionInfo = new SocketConnectionInfo(socket, connectionId);
				dictionary.TryAdd(socket, socketConnectionInfo);
			}
			return socketConnectionInfo;
		}

		public SocketConnectionInfo GetSocketConnectionInfo(string uniqueId)
		{
			SocketConnectionInfo socketConnectionInfo = null;
			foreach (var item in dictionary)
			{
				if (string.Compare(item.Value?.ConnectionId, uniqueId, true) == 0)
				{
					if (item.Value.ReceivedTimeFromServer >= socketConnectionInfo?.ReceivedTimeFromServer)
					{
						Remove(socketConnectionInfo.CurrentSocket);
					}
					else
					{
						socketConnectionInfo = item.Value;
					}

				}
			}

			return socketConnectionInfo;
		}

		public void Remove(IWebSocketConnection socket)
		{
			if (socket != null)
			{
				dictionary.TryRemove(socket, out SocketConnectionInfo value);
				try
				{
					//判断此连接是否可用
					if (socket.IsAvailable)
					{
						socket.Close();
					}
				}
				catch
				{
					throw;
				}
				socket.Close();
				value = null;
			}
		}

		public void RemoveAll()
		{
			foreach (var item in dictionary)
			{
				item.Value?.Close();
			}
			dictionary.Clear();
		}

		public int Count
		{
			get
			{
				if (dictionary == null)
				{
					return 0;
				}
				return dictionary.Count;
			}
		}

	}
}

  调用方式

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

namespace DB
{
	public class DBHelper
	{

		private static object obj = new object();
		private static SocketConnectionInfoFactory webSocket = null;

		public static SocketConnectionInfoFactory GetInstance()
		{
			if (webSocket == null)
			{
				lock (obj)
				{
					if (webSocket == null)
					{
						webSocket = new SocketConnectionInfoFactory();
					}
				}
			}
			return webSocket;

		}
	}
}

  

socket 一个websocke对应一个socketclient对象的更多相关文章

  1. .Net开发笔记(十九) 创建一个可以可视化设计的对象

    阅读本篇博客之前需要了解VS窗体设计器的工作原理,详细可参见本系列博客(十).(十一).(十二).必须需要知道的一条结论就是:处于窗体设计器(Form Designer)中的任何组件(包含控件,下同) ...

  2. threadlocal精髓是为每一个线程保证一个共享对象,保证一个,保证是同一个

    threadlocal精髓是为每一个线程保证一个共享对象,保证一个,保证同一个线程中是同一个共享对象. 如果是静态变量是共享的话,那必须同步,否则尽管有副本,还是会出错,故C错

  3. Tiny Mapper是一个.net平台开源的对象映射组件

    NET平台开源项目速览(14)最快的对象映射组件Tiny Mapper   阅读目录 1.Tiny Mapper基本介绍 2.Tiny Mapper 基本使用 3.Tiny Mapper 指定配置使用 ...

  4. 27、通过visual s'tudio 验证 SOCKET编程:搭建一个TCP服务器

    本文就是在windows下进行socket编程,搭建一个TCP客户端. 在visual studio下编程,首先在windows下进行初始化(这点在linux下是不需要的): /* 初始化 Winso ...

  5. 通过一个uri获取一个Bitmap对象

    Android 开发过程中,可能会用到的,通过一个uri获取一个Bitmap对象 private Bitmap getBitmapFromUri(Uri uri){  try  {   // 读取ur ...

  6. C#中如果用await关键字来await一个为null的Task对象会抛出异常

    await & async模式是C#中一个很重要的特性,可以用来提高异步程序(多线程程序)的执行效率.但是如果尝试用await关键字来await一个为null的Task对象,会导致程序抛出Nu ...

  7. Object.assign() 从一个或多个源对象复制到目标对象

    Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. 1.语法: Object.assign(target, ... , sources) 参 ...

  8. 创建一个doc对象时候 如果读取了一个已存在的xml对象时候 该xml对象的结构已存在doc中 当改变该doc结构时候 不需要创建新的doc对象

    创建一个doc对象时候 如果读取了一个已存在的xml对象时候 该xml对象的结构已存在doc中 当改变该doc结构时候不 需要创建新的doc对象 直接添加即可 他会同步过去

  9. iter创建一个可以被迭代的对象

    #!/usr/bin/env python obj = iter([11,22,33,44]) #iter 创建一个可以被迭代的对象 print(obj) r1 = next(obj) print(r ...

随机推荐

  1. HTML+CSS基础学习标签代码

    HTML基础 一.HTML页面结构 1.HTML定义 (HTML)为超文本标记语言,是写给浏览器的语言, 目前网络上应用最广泛的语言,目前已经更新到HTML5,HTML添加了一些写的语义化标签,放弃了 ...

  2. 洛谷 P3374 【模板】树状数组 1 & P3368 【模板】树状数组 2 题解

    一维树状数组的作用主要是单点修改,单点查询,区间修改,区间查询. 模板1是单点修改,区间查询:模板2是单点查询,区间修改. 模板1: #include<iostream> #include ...

  3. /etc/sysconfig/network-scripts/ifcfg-ensxx

    TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=static # 获取ip的方式,static表示静态设置的ip,还有dhcp,系统 ...

  4. Crontab 定时任务格式参数

    crontab 定时执行 任务 格式: * * * * *-) 小时(-) 日(-) 月份(-) 星期(-6) 星号(*):代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条 ...

  5. NetworkX系列教程(1)-创建graph

    小书匠Graph图论 研究中经常涉及到图论的相关知识,而且常常面对某些术语时,根本不知道在说什么.前不久接触了NetworkX这个graph处理工具,发现这个工具已经解决绝大部分的图论问题(也许只是我 ...

  6. (1)打鸡儿教你Vue.js

    当今世界不会Vue.js,前端必定路难走 一个JavaScript MVVM库 以数据驱动和组件化的思想构建的 Vue.js是数据驱动 HTML/CSS/JavaScript/ES6/HTTP协议/V ...

  7. spark常见错误【持续更新】

    错误1.错误: 找不到或无法加载主类 idea.scala代码 idea 导入的scala工程,编写代码后报该错误. 原因:\src\main\scala 包路径下没有将scala这个包设置成Sour ...

  8. nmon服务器性能结果报告分析

    一.nmon命令 ./nmon_x86_64_centos7 -f -s 10 -c 60 -m ./log/  命令的含义是: -f :按标准格式输出文件名称:<hostname>_YY ...

  9. [bzoj 2768]&[bzoj 1877]

    传送门1 传送门1 Solution 两道比较裸的题... 复习一下最大流和费用流的模板. Code[bzoj 2768][JLOI 2010] 冠军调查 #include<bits/stdc+ ...

  10. 数据库——JavaWEB数据库连接

    一.数据库连接的发展 1.数据库连接 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...