|
|
@@ -116,7 +116,15 @@ namespace ET
|
|
|
this.socket.ReceiveBufferSize = Kcp.OneM * 64;
|
|
|
}
|
|
|
|
|
|
- this.socket.Bind(ipEndPoint);
|
|
|
+ try
|
|
|
+ {
|
|
|
+ this.socket.Bind(ipEndPoint);
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ throw new Exception($"bind error: {ipEndPoint}", e);
|
|
|
+ }
|
|
|
+
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
{
|
|
|
const uint IOC_IN = 0x80000000;
|
|
|
@@ -142,7 +150,6 @@ namespace ET
|
|
|
}
|
|
|
|
|
|
// 保存所有的channel
|
|
|
- private readonly Dictionary<long, KChannel> idChannels = new Dictionary<long, KChannel>();
|
|
|
private readonly Dictionary<long, KChannel> localConnChannels = new Dictionary<long, KChannel>();
|
|
|
private readonly Dictionary<long, KChannel> waitConnectChannels = new Dictionary<long, KChannel>();
|
|
|
|
|
|
@@ -150,18 +157,8 @@ namespace ET
|
|
|
private EndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, 0);
|
|
|
|
|
|
// 下帧要更新的channel
|
|
|
- private readonly HashSet<long> updateChannels = new HashSet<long>();
|
|
|
+ private readonly HashSet<long> updateIds = new HashSet<long>();
|
|
|
|
|
|
- // 下次时间更新的channel
|
|
|
- private readonly MultiMap<long, long> timeId = new MultiMap<long, long>();
|
|
|
-
|
|
|
- private readonly List<long> timeOutTime = new List<long>();
|
|
|
-
|
|
|
- // 记录最小时间,不用每次都去MultiMap取第一个值
|
|
|
- private long minTime;
|
|
|
-
|
|
|
- private readonly List<long> waitRemoveChannels = new List<long>();
|
|
|
-
|
|
|
public override bool IsDispose()
|
|
|
{
|
|
|
return this.socket == null;
|
|
|
@@ -171,7 +168,7 @@ namespace ET
|
|
|
{
|
|
|
base.Dispose();
|
|
|
|
|
|
- foreach (long channelId in this.idChannels.Keys.ToArray())
|
|
|
+ foreach (long channelId in this.localConnChannels.Keys.ToArray())
|
|
|
{
|
|
|
this.Remove(channelId);
|
|
|
}
|
|
|
@@ -238,13 +235,13 @@ namespace ET
|
|
|
// 这里必须校验localConn,客户端重连,localConn一定是一样的
|
|
|
if (localConn != kChannel.LocalConn)
|
|
|
{
|
|
|
- Log.Warning($"kchannel reconnect localconn error: {kChannel.Id} {localConn} {remoteConn} {realAddress} {kChannel.LocalConn}");
|
|
|
+ Log.Warning($"kchannel reconnect localconn error: {localConn} {remoteConn} {realAddress} {kChannel.LocalConn}");
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (remoteConn != kChannel.RemoteConn)
|
|
|
{
|
|
|
- Log.Warning($"kchannel reconnect remoteconn error: {kChannel.Id} {localConn} {remoteConn} {realAddress} {kChannel.RemoteConn}");
|
|
|
+ Log.Warning($"kchannel reconnect remoteconn error: {localConn} {remoteConn} {realAddress} {kChannel.RemoteConn}");
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
@@ -292,21 +289,16 @@ namespace ET
|
|
|
this.waitConnectChannels.TryGetValue(remoteConn, out kChannel);
|
|
|
if (kChannel == null)
|
|
|
{
|
|
|
- // accept的localConn不能与内网进程号的ChannelId冲突,所以设置为一个大的随机数
|
|
|
- localConn = NetServices.Instance.CreateRandomLocalConn();
|
|
|
+ // accept的localConn不能与connect的localConn冲突,所以设置为一个大的数
|
|
|
+ // localConn被人猜出来问题不大,因为remoteConn是随机的第三方并不知道
|
|
|
+ localConn = NetServices.Instance.CreateAcceptChannelId();
|
|
|
// 已存在同样的localConn,则不处理,等待下次sync
|
|
|
if (this.localConnChannels.ContainsKey(localConn))
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
- long id = NetServices.Instance.CreateAcceptChannelId(localConn);
|
|
|
- if (this.idChannels.ContainsKey(id))
|
|
|
- {
|
|
|
- break;
|
|
|
- }
|
|
|
|
|
|
- kChannel = new KChannel(id, localConn, remoteConn, this.socket, this.CloneAddress(), this);
|
|
|
- this.idChannels.Add(kChannel.Id, kChannel);
|
|
|
+ kChannel = new KChannel(localConn, remoteConn, this.socket, this.CloneAddress(), this);
|
|
|
this.waitConnectChannels.Add(kChannel.RemoteConn, kChannel); // 连接上了或者超时后会删除
|
|
|
this.localConnChannels.Add(kChannel.LocalConn, kChannel);
|
|
|
|
|
|
@@ -353,10 +345,10 @@ namespace ET
|
|
|
|
|
|
remoteConn = BitConverter.ToUInt32(this.cache, 1);
|
|
|
localConn = BitConverter.ToUInt32(this.cache, 5);
|
|
|
- kChannel = this.GetByLocalConn(localConn);
|
|
|
+ kChannel = this.Get(localConn);
|
|
|
if (kChannel != null)
|
|
|
{
|
|
|
- Log.Info($"kservice ack: {kChannel.Id} {remoteConn} {localConn}");
|
|
|
+ Log.Info($"kservice ack: {localConn} {remoteConn}");
|
|
|
kChannel.RemoteConn = remoteConn;
|
|
|
kChannel.HandleConnnect();
|
|
|
}
|
|
|
@@ -374,7 +366,7 @@ namespace ET
|
|
|
int error = BitConverter.ToInt32(this.cache, 9);
|
|
|
|
|
|
// 处理chanel
|
|
|
- kChannel = this.GetByLocalConn(localConn);
|
|
|
+ kChannel = this.Get(localConn);
|
|
|
if (kChannel == null)
|
|
|
{
|
|
|
break;
|
|
|
@@ -386,7 +378,7 @@ namespace ET
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- Log.Info($"kservice recv fin: {kChannel.Id} {localConn} {remoteConn} {error}");
|
|
|
+ Log.Info($"kservice recv fin: {localConn} {remoteConn} {error}");
|
|
|
kChannel.OnError(ErrorCore.ERR_PeerDisconnect);
|
|
|
|
|
|
break;
|
|
|
@@ -400,7 +392,7 @@ namespace ET
|
|
|
remoteConn = BitConverter.ToUInt32(this.cache, 1);
|
|
|
localConn = BitConverter.ToUInt32(this.cache, 5);
|
|
|
|
|
|
- kChannel = this.GetByLocalConn(localConn);
|
|
|
+ kChannel = this.Get(localConn);
|
|
|
if (kChannel == null)
|
|
|
{
|
|
|
// 通知对方断开
|
|
|
@@ -413,7 +405,13 @@ namespace ET
|
|
|
{
|
|
|
break;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ // 对方发来msg,说明kchannel连接完成
|
|
|
+ if (!kChannel.IsConnected)
|
|
|
+ {
|
|
|
+ kChannel.IsConnected = true;
|
|
|
+ this.waitConnectChannels.Remove(remoteConn);
|
|
|
+ }
|
|
|
kChannel.HandleRecv(this.cache, 5, messageLength - 5);
|
|
|
break;
|
|
|
}
|
|
|
@@ -428,20 +426,13 @@ namespace ET
|
|
|
public KChannel Get(long id)
|
|
|
{
|
|
|
KChannel channel;
|
|
|
- this.idChannels.TryGetValue(id, out channel);
|
|
|
- return channel;
|
|
|
- }
|
|
|
-
|
|
|
- private KChannel GetByLocalConn(uint localConn)
|
|
|
- {
|
|
|
- KChannel channel;
|
|
|
- this.localConnChannels.TryGetValue(localConn, out channel);
|
|
|
+ this.localConnChannels.TryGetValue(id, out channel);
|
|
|
return channel;
|
|
|
}
|
|
|
|
|
|
public override void Create(long id, IPEndPoint address)
|
|
|
{
|
|
|
- if (this.idChannels.TryGetValue(id, out KChannel kChannel))
|
|
|
+ if (this.localConnChannels.TryGetValue(id, out KChannel kChannel))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
@@ -449,9 +440,8 @@ namespace ET
|
|
|
try
|
|
|
{
|
|
|
// 低32bit是localConn
|
|
|
- uint localConn = (uint) ((ulong) id & uint.MaxValue);
|
|
|
- kChannel = new KChannel(id, localConn, this.socket, address, this);
|
|
|
- this.idChannels.Add(id, kChannel);
|
|
|
+ uint localConn = (uint)id;
|
|
|
+ kChannel = new KChannel(localConn, this.socket, address, this);
|
|
|
this.localConnChannels.Add(kChannel.LocalConn, kChannel);
|
|
|
}
|
|
|
catch (Exception e)
|
|
|
@@ -462,12 +452,12 @@ namespace ET
|
|
|
|
|
|
public override void Remove(long id)
|
|
|
{
|
|
|
- if (!this.idChannels.TryGetValue(id, out KChannel kChannel))
|
|
|
+ if (!this.localConnChannels.TryGetValue(id, out KChannel kChannel))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
Log.Info($"kservice remove channel: {id} {kChannel.LocalConn} {kChannel.RemoteConn}");
|
|
|
- this.idChannels.Remove(id);
|
|
|
+ this.localConnChannels.Remove(id);
|
|
|
this.localConnChannels.Remove(kChannel.LocalConn);
|
|
|
if (this.waitConnectChannels.TryGetValue(kChannel.RemoteConn, out KChannel waitChannel))
|
|
|
{
|
|
|
@@ -523,9 +513,12 @@ namespace ET
|
|
|
{
|
|
|
this.Recv();
|
|
|
|
|
|
- this.TimerOut();
|
|
|
-
|
|
|
- foreach (long id in updateChannels)
|
|
|
+ this.UpdateChannel();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void UpdateChannel()
|
|
|
+ {
|
|
|
+ foreach (long id in this.updateIds)
|
|
|
{
|
|
|
KChannel kChannel = this.Get(id);
|
|
|
if (kChannel == null)
|
|
|
@@ -540,96 +533,13 @@ namespace ET
|
|
|
|
|
|
kChannel.Update();
|
|
|
}
|
|
|
-
|
|
|
- this.updateChannels.Clear();
|
|
|
-
|
|
|
- this.RemoveConnectTimeoutChannels();
|
|
|
- }
|
|
|
-
|
|
|
- private void RemoveConnectTimeoutChannels()
|
|
|
- {
|
|
|
- waitRemoveChannels.Clear();
|
|
|
- foreach (long channelId in this.waitConnectChannels.Keys)
|
|
|
- {
|
|
|
- this.waitConnectChannels.TryGetValue(channelId, out KChannel kChannel);
|
|
|
- if (kChannel == null)
|
|
|
- {
|
|
|
- Log.Error($"RemoveConnectTimeoutChannels not found kchannel: {channelId}");
|
|
|
- continue;
|
|
|
- }
|
|
|
-
|
|
|
- // 连接上了要马上删除
|
|
|
- if (kChannel.IsConnected)
|
|
|
- {
|
|
|
- waitRemoveChannels.Add(channelId);
|
|
|
- }
|
|
|
-
|
|
|
- // 10秒连接超时
|
|
|
- if (this.TimeNow > kChannel.CreateTime + 10 * 1000)
|
|
|
- {
|
|
|
- waitRemoveChannels.Add(channelId);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- foreach (long channelId in waitRemoveChannels)
|
|
|
- {
|
|
|
- this.waitConnectChannels.Remove(channelId);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 计算到期需要update的channel
|
|
|
- private void TimerOut()
|
|
|
- {
|
|
|
- if (this.timeId.Count == 0)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- uint timeNow = this.TimeNow;
|
|
|
-
|
|
|
- if (timeNow < this.minTime)
|
|
|
- {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- this.timeOutTime.Clear();
|
|
|
-
|
|
|
- foreach (KeyValuePair<long, List<long>> kv in this.timeId)
|
|
|
- {
|
|
|
- long k = kv.Key;
|
|
|
- if (k > timeNow)
|
|
|
- {
|
|
|
- minTime = k;
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- this.timeOutTime.Add(k);
|
|
|
- }
|
|
|
-
|
|
|
- foreach (long k in this.timeOutTime)
|
|
|
- {
|
|
|
- foreach (long v in this.timeId[k])
|
|
|
- {
|
|
|
- this.updateChannels.Add(v);
|
|
|
- }
|
|
|
-
|
|
|
- this.timeId.Remove(k);
|
|
|
- }
|
|
|
+ this.updateIds.Clear();
|
|
|
}
|
|
|
|
|
|
// 服务端需要看channel的update时间是否已到
|
|
|
- public void AddToUpdate(long time, long id)
|
|
|
+ public void AddToUpdate(long id)
|
|
|
{
|
|
|
- if (time == 0)
|
|
|
- {
|
|
|
- this.updateChannels.Add(id);
|
|
|
- return;
|
|
|
- }
|
|
|
- if (time < this.minTime)
|
|
|
- {
|
|
|
- this.minTime = time;
|
|
|
- }
|
|
|
- this.timeId.Add(time, id);
|
|
|
+ this.updateIds.Add(id);
|
|
|
}
|
|
|
}
|
|
|
}
|