123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- using Microsoft.IO;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Net.Sockets;
- namespace WS
- {
- ///<summary>TCP服务</summary>
- public sealed class TService : AService
- {
- ///<summary>一个异步操作一个TChannel(一个Socket链接)</summary>
- private readonly Dictionary<long, TChannel> idChannels = new Dictionary<long, TChannel>();
- ///<summary>Socket异步操作</summary>
- private readonly SocketAsyncEventArgs innArgs = new SocketAsyncEventArgs();
- ///<summary>Socket</summary>
- private Socket server;
- ///<summary>性能的.NET流管理</summary>
- public RecyclableMemoryStreamManager MemoryStreamManager = new RecyclableMemoryStreamManager();
- ///<summary>需要开始发送的TChannel 哈希表</summary>
- public HashSet<long> needStartSendChannel = new HashSet<long>();
- ///<summary>包头长度</summary>
- public int PacketSizeLength { get; }
- /// <summary>server</summary>
- /// <param name="packetSizeLength">包头长度</param>
- /// <param name="ipEndPoint">IP 端口</param>
- /// <param name="acceptCallback">Accept 接收回调</param>
- public TService(int packetSizeLength, IPEndPoint ipEndPoint, Action<AChannel> acceptCallback)
- {
- PacketSizeLength = packetSizeLength;
- AcceptCallback += acceptCallback;
- server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//创建服务器监听
- server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
- innArgs.Completed += OnComplete;//注册异步操作回调
- server.Bind(ipEndPoint);//创建Serer链接
- server.Listen(1000);
- Log.LogDebug("服务器启动成功!");
- AcceptAsync();
- }
- /// <summary>client</summary>
- public TService(int packetSizeLength)
- {
- PacketSizeLength = packetSizeLength;
- }
- public override void Dispose()
- {
- if (IsDisposed)
- {
- return;
- }
- base.Dispose();
- foreach (long id in idChannels.Keys.ToArray())
- {
- TChannel channel = idChannels[id];
- channel.Dispose();
- }
- server?.Close();
- server = null;
- innArgs.Dispose();
- }
- ///<summary>异步操作回调</summary>
- private void OnComplete(object sender, SocketAsyncEventArgs e)
- {
- switch (e.LastOperation)
- {
- case SocketAsyncOperation.Accept://接收客户端链接操作
- OneThreadSynchronizationContext.Instance.Post(OnAcceptComplete, e);
- break;
- default:
- throw new Exception($"socket accept error: {e.LastOperation}");
- }
- }
- ///<summary>接收客户端的Socket</summary>
- public void AcceptAsync()
- {
- innArgs.AcceptSocket = null;
- if (server.AcceptAsync(innArgs))//开始监听客服端链接=>如果返回值为true 表明挂起异步等待返回,如果返回值为false 表明回调完成跳过回调直接执行
- {
- return;
- }
- OnAcceptComplete(innArgs);
- }
- ///<summary>接收客户端的Socket链接完成回调</summary>
- private void OnAcceptComplete(object o)
- {
- if (server == null) return;
-
- SocketAsyncEventArgs e = (SocketAsyncEventArgs)o;
- if (e.SocketError != SocketError.Success)//如果不等于操作成功
- {
- Log.LogError($"accept error {e.SocketError}");
- AcceptAsync();//继续监听客户端链接
- return;
- }
- TChannel channel = new TChannel(e.AcceptSocket, this);//创建客户端Socket链接
- idChannels[channel.InstanceId] = channel;
- try
- {
- OnAccept(channel);//Socket链接成功 =》调用接收成功事件 到=》NetworkComponent
- }
- catch (Exception exception)
- {
- Log.LogError(exception);
- }
- if (server == null) return;
- AcceptAsync();//继续监听客户端链接
- }
- ///<summary>获取Channel 渠道</summary>
- public override AChannel GetChannel(long id)
- {
- TChannel channel = null;
- idChannels.TryGetValue(id, out channel);
- return channel;
- }
- #region -- Channel --
- ///<summary>链接Channel 渠道</summary>
- public override AChannel ConnectChannel(IPEndPoint ipEndPoint)
- {
- TChannel channel = new TChannel(ipEndPoint, this);
- idChannels[channel.InstanceId] = channel;
- return channel;
- }
- ///<summary>链接Channel 渠道</summary>
- public override AChannel ConnectChannel(string address)
- {
- IPEndPoint ipEndPoint = NetworkHelper.ToIPEndPoint(address);
- return ConnectChannel(ipEndPoint);
- }
- ///<summary>标记需要开始发送</summary>
- public void MarkNeedStartSend(long id)
- {
- needStartSendChannel.Add(id);
- }
- ///<summary>删除Channel 渠道</summary>
- public override void Remove(long id)
- {
- TChannel channel;
- if (!idChannels.TryGetValue(id, out channel)) return;
-
- if (channel == null) return;
-
- idChannels.Remove(id);
- channel.Dispose();
- }
- #endregion
- public override void Update()
- {
- foreach (long id in needStartSendChannel)
- {
- TChannel channel;
- if (!idChannels.TryGetValue(id, out channel))
- continue;
- if (channel.IsSending)
- continue;
- try
- {
- channel.StartSend();
- }
- catch (Exception e)
- {
- Log.LogError(e);
- }
- }
- needStartSendChannel.Clear();
- }
- }
- }
|