summaryrefslogtreecommitdiff
path: root/Client/Assembly-CSharp/InnerNet/InnerNetClient.cs
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-01-02 01:22:42 +0800
committerchai <chaifix@163.com>2021-01-02 01:22:42 +0800
commit59755580acab0de7bfc88482b6a515b546d45cd7 (patch)
tree218b063a2fa0af05866ee177d3ed8886b91bcbec /Client/Assembly-CSharp/InnerNet/InnerNetClient.cs
parentbe6caf20c319f55fe6fa5d918859af39991a899f (diff)
*网络
Diffstat (limited to 'Client/Assembly-CSharp/InnerNet/InnerNetClient.cs')
-rw-r--r--Client/Assembly-CSharp/InnerNet/InnerNetClient.cs114
1 files changed, 86 insertions, 28 deletions
diff --git a/Client/Assembly-CSharp/InnerNet/InnerNetClient.cs b/Client/Assembly-CSharp/InnerNet/InnerNetClient.cs
index b88dda4..3336804 100644
--- a/Client/Assembly-CSharp/InnerNet/InnerNetClient.cs
+++ b/Client/Assembly-CSharp/InnerNet/InnerNetClient.cs
@@ -14,6 +14,7 @@ namespace InnerNet
{
public abstract class InnerNetClient : MonoBehaviour
{
+ // 是否连接成功
private bool AmConnected
{
get
@@ -22,6 +23,7 @@ namespace InnerNet
}
}
+ // ping
public int Ping
{
get
@@ -88,6 +90,7 @@ namespace InnerNet
private int networkPort;
+ // Udp连接
private UdpClientConnection connection;
public MatchMakerModes mode;
@@ -98,6 +101,7 @@ namespace InnerNet
public int ClientId = -1;
+ // 本局内的所有玩家的数据,包括cliendId,playercontrol
public List<ClientData> allClients = new List<ClientData>();
public DisconnectReasons LastDisconnectReason;
@@ -155,18 +159,20 @@ namespace InnerNet
public enum GameStates
{
- NotJoined,
- Joined,
- Started,
- Ended
+ NotJoined, //
+ Joined, //
+ Started, //
+ Ended //
}
+ // 每次开局的时候设置remote endpoint
public void SetEndpoint(string addr, ushort port)
{
this.networkAddress = addr;
this.networkPort = (int)port;
}
+ // 初始化
public virtual void Start()
{
SceneManager.activeSceneChanged += delegate(Scene oldScene, Scene scene)
@@ -190,6 +196,7 @@ namespace InnerNet
}
}
+ // 找到作为host的主机数据
public ClientData GetHost()
{
List<ClientData> obj = this.allClients;
@@ -207,7 +214,8 @@ namespace InnerNet
return null;
}
- public int GetClientIdFromCharacter(InnerNetObject character)
+ // 根据playerControl找到对应的clientId
+ public int GetClientIdFromCharacter(InnerNetObject /*PlayerControl*/ character)
{
if (!character)
{
@@ -228,6 +236,7 @@ namespace InnerNet
return -1;
}
+ // 销毁的时候断开连接
public virtual void OnDestroy()
{
if (this.AmConnected)
@@ -236,6 +245,7 @@ namespace InnerNet
}
}
+ // 只建立“udp连接”,不建房间
public IEnumerator CoConnect()
{
if (this.AmConnected)
@@ -266,6 +276,11 @@ namespace InnerNet
messageWriter.Write(this.GameId);
}
+ // 建立连接
+ // 因为是Udp所以实际上socket没有调用connect函数,ConnectAsync的第二个参数timeout只是在第一次建立连接的时候向服务器发送一个
+ // hello消息,确保连接成功
+ // Hazel-Networking的Udp连接风格实现了和Tcp一样的方式,这样容易被客户端使用,将游戏过程中共用的数据比如Ip,端口,封装为一个
+ // Udp连接,方便统一管理
IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(this.networkAddress), this.networkPort);
this.connection = new UdpClientConnection(remoteEndPoint, IPMode.IPv4);
this.connection.KeepAliveInterval = 1500;
@@ -273,23 +288,25 @@ namespace InnerNet
this.connection.ResendPingMultiplier = 2f;
this.connection.DataReceived += this.OnMessageReceived; // 注册到网络线程的消息处理函数
this.connection.Disconnected += this.OnDisconnect; // 连接断开时的回调函数
+
+ // “建立连接”并尝试向服务器发送一个hello消息,保证连接是通的
this.connection.ConnectAsync(this.GetConnectionData(), 5000);
- yield return this.WaitWithTimeout(() => this.connection == null || this.connection.State == ConnectionState.Connected);
+ yield return this.WaitWithTimeout(
+ () => this.connection == null || this.connection.State == ConnectionState.Connected
+ );
yield break;
}
private void Connection_DataReceivedRaw(byte[] data)
{
- Debug.Log("Client Got: " + string.Join(" ", from b in data
- select b.ToString()));
+ Debug.Log("Client Got: " + string.Join(" ", from b in data select b.ToString()));
}
private void Connection_DataSentRaw(byte[] data, int length)
{
- Debug.Log("Client Sent: " + string.Join(" ", (from b in data
- select b.ToString()).ToArray<string>(), 0, length));
+ Debug.Log("Client Sent: " + string.Join(" ", (from b in data select b.ToString()).ToArray<string>(), 0, length));
}
public void Connect(MatchMakerModes mode)
@@ -297,6 +314,7 @@ namespace InnerNet
base.StartCoroutine(this.CoConnect(mode));
}
+ // 这个协程包括了建立udp连接和建立host服务器(如果是MatchMakerModes.HostAndClient的话)或加入游戏(如果是MatchMakerModes.Client)
private IEnumerator CoConnect(MatchMakerModes mode)
{
if (this.mode != MatchMakerModes.None)
@@ -304,38 +322,57 @@ namespace InnerNet
this.DisconnectInternal(DisconnectReasons.NewConnection, null);
}
this.mode = mode;
+
+ // “udp连接”
yield return this.CoConnect();
- if (!this.AmConnected)
+
+ if (!this.AmConnected) // 连接失败
{
yield break;
}
+ // 连接成功
+
MatchMakerModes matchMakerModes = this.mode;
- if (matchMakerModes == MatchMakerModes.Client)
+ if (matchMakerModes == MatchMakerModes.Client) // 如果在本局只作为client,加入游戏
{
- this.JoinGame();
- yield return this.WaitWithTimeout(() => this.ClientId >= 0);
+ this.JoinGame(); // 加入游戏
+ yield return this.WaitWithTimeout(
+ () => this.ClientId >= 0 // clientId大于0代表加入游戏成功
+ );
bool amConnected = this.AmConnected;
yield break;
}
- if (matchMakerModes != MatchMakerModes.HostAndClient)
+ // 下面是作为host建立房间
+
+ if (matchMakerModes != MatchMakerModes.HostAndClient)
{
yield break;
}
this.GameId = 0;
- // 单局游戏配置
+
+ // 单局游戏的配置,本玩家作为host建立游戏
PlayerControl.GameOptions = SaveManager.GameHostOptions;
- this.HostGame(PlayerControl.GameOptions); // 作为host
- yield return this.WaitWithTimeout(() => this.GameId != 0);
- if (!this.AmConnected)
+ // 作为host创建游戏
+ this.HostGame(PlayerControl.GameOptions);
+ yield return this.WaitWithTimeout(
+ () => this.GameId != 0 // gameId不为0代表建立游戏成功,对应InnerNetServer.cs中的HandleMessage
+ );
+
+ if (!this.AmConnected) // 连接失败
{
yield break;
}
- this.JoinGame();
- yield return this.WaitWithTimeout(() => this.ClientId >= 0);
+
+ this.JoinGame(); // 加入游戏
+
+ yield return this.WaitWithTimeout(
+ () => this.ClientId >= 0 // clientId大于0代表加入游戏成功
+ );
bool amConnected2 = this.AmConnected;
yield break;
}
+ // 等待连接建立
public IEnumerator WaitForConnectionOrFail()
{
while (this.AmConnected)
@@ -367,6 +404,7 @@ namespace InnerNet
yield break;
}
+ // 每帧检查一下success是否达成,并检查timeout,超过timeout限制后fail
private IEnumerator WaitWithTimeout(Func<bool> success)
{
bool failed = true;
@@ -383,6 +421,7 @@ namespace InnerNet
}
yield return null;
}
+ // 超时,断开连接
if (failed)
{
this.DisconnectInternal(DisconnectReasons.Error, null);
@@ -440,6 +479,7 @@ namespace InnerNet
}
}
+ // 断开连接的回调,在网络线程调用
private void OnDisconnect(object sender, DisconnectedEventArgs e)
{
if (!e.Reason.Contains("The remote sent a"))
@@ -459,6 +499,7 @@ namespace InnerNet
this.OnDisconnected();
}
+ // 将主动断开连接的任务加到dispatcher,待主线程执行
protected void EnqueueDisconnect(DisconnectReasons reason, string stringReason = null)
{
UdpClientConnection udpClientConnection = this.connection;
@@ -472,6 +513,7 @@ namespace InnerNet
}
}
+ // 主动断开连接
protected void DisconnectInternal(DisconnectReasons reason, string stringReason = null)
{
if (reason != DisconnectReasons.NewConnection && reason != DisconnectReasons.FocusLostBackground)
@@ -536,13 +578,14 @@ namespace InnerNet
this.IsGamePublic = false;
MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
messageWriter.StartMessage(0);
- messageWriter.WriteBytesAndSize(settings.ToBytes());
+ messageWriter.WriteBytesAndSize(settings.ToBytes()); // 这里当作为InnerNetServer启动时没有用到,中心服务器需要这个字段是因为要显示房间列表
messageWriter.EndMessage();
this.SendOrDisconnect(messageWriter);
messageWriter.Recycle();
Debug.Log("Client requesting new game.");
}
+ // 加入游戏
public void JoinGame()
{
this.ClientId = -1;
@@ -560,16 +603,19 @@ namespace InnerNet
messageWriter.Recycle();
}
+ // 是否可以ban其他玩家(只有房主可以)
public bool CanBan()
{
return this.AmHost && !this.IsGameStarted;
}
+ // 是否可以踢其他玩家
public bool CanKick()
{
return this.IsGameStarted || this.AmHost;
}
+ // 踢玩家
public void KickPlayer(int clientId, bool ban)
{
if (!this.AmHost)
@@ -586,6 +632,7 @@ namespace InnerNet
messageWriter.Recycle();
}
+ // 结束游戏
public MessageWriter StartEndGame()
{
MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
@@ -1043,6 +1090,7 @@ namespace InnerNet
});
}
+ // 根据clientID返回对应的client结构,如果没有的话新建一个并保存
private ClientData GetOrCreateClient(int clientId)
{
List<ClientData> obj = this.allClients;
@@ -1059,6 +1107,7 @@ namespace InnerNet
return clientData;
}
+ //在网络线程调用,删除某个角色gameobject
private void RemovePlayer(int playerIdThatLeft, DisconnectReasons reason)
{
ClientData client = null;
@@ -1083,12 +1132,14 @@ namespace InnerNet
{
this.Dispatcher.Add(delegate
{
+ // 在主线程调用
this.OnPlayerLeft(client, reason);
});
}
}
}
+ //
protected virtual void OnApplicationPause(bool pause)
{
this.appPaused = pause;
@@ -1123,6 +1174,7 @@ namespace InnerNet
}
}
+ //
protected void SendInitialData(int clientId)
{
MessageWriter messageWriter = MessageWriter.Get(SendOption.Reliable);
@@ -1171,6 +1223,7 @@ namespace InnerNet
protected abstract byte[] GetConnectionData();
+ // 根据clientId返回对应的client结构
protected ClientData FindClientById(int id)
{
if (id < 0)
@@ -1265,7 +1318,7 @@ namespace InnerNet
for (int j = 0; j < this.Streams.Length; j++)
{
MessageWriter messageWriter2 = this.Streams[j];
- /*
+ /*
public void StartMessage(byte typeFlag)
{
messageStarts.Push(this.Position);
@@ -1280,11 +1333,11 @@ namespace InnerNet
this.Buffer[lastMessageStart + 1] = (byte)(length >> 8);
}
*/
- if (messageWriter2.HasBytes(7)) // 里面是否有数据,有的话发送。7=length(2B) + DataFlag(1B) + netId(4B)
- {
+ // 里面是否有数据,有的话发送。
+ if (messageWriter2.HasBytes(7)) // 7=length(2B) + DataFlag(1B) + netId(4B)
+ {
messageWriter2.EndMessage();
this.SendOrDisconnect(messageWriter2);
-
messageWriter2.Clear((SendOption)j);
messageWriter2.StartMessage(5); // 初始化
messageWriter2.Write(this.GameId);
@@ -1292,6 +1345,7 @@ namespace InnerNet
}
}
+ // 根据netId返回对应的同步对象
public T FindObjectByNetId<T>(uint netId) where T : InnerNetObject
{
InnerNetObject innerNetObject;
@@ -1317,6 +1371,7 @@ namespace InnerNet
messageWriter.Recycle();
}
+ // 封装一个Rpc,配合FinishRpcImmediately
public MessageWriter StartRpcImmediately(uint targetNetId, byte callId, SendOption option, int targetClientId = -1)
{
MessageWriter messageWriter = MessageWriter.Get(option);
@@ -1345,10 +1400,11 @@ namespace InnerNet
msg.Recycle();
}
- //
+ // 向公用的stream写入Rpc
public void SendRpc(uint targetNetId, byte callId, SendOption option = SendOption.Reliable)
{
- this.StartRpc(targetNetId, callId, option).EndMessage();
+ this.StartRpc(targetNetId, callId, option)
+ .EndMessage();
}
public MessageWriter StartRpc(uint targetNetId, byte callId, SendOption option = SendOption.Reliable)
@@ -1360,6 +1416,7 @@ namespace InnerNet
return messageWriter;
}
+ // 发送切换场景消息
private void SendSceneChange(string sceneName)
{
this.InOnlineScene = string.Equals(sceneName, "OnlineGame");
@@ -1746,6 +1803,7 @@ namespace InnerNet
}) + string.Join<byte>(" ", reader.Buffer));
}
+ // 延迟发送消息
private void DeferMessage(int cnt, MessageReader reader, string logMsg)
{
if (cnt > 10)