ro-webgl/Assets/Src/Core/Network/SocketConn.cs

391 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using UnityEngine;
using UnityWebSocket;
public enum enSocketState
{
Connecting, //建立连接中
Reconnecting, //重新连接中
Connected, //连接成功
Disconnecting, //断开连接中
Disconnected, //连接断开
ConnectedTimeout, //连接超时
ConnectedError, //连接出错
}
public class SocketConn
{
string mName;
string mLastIP;
int mLastPort;
Socket mSocket;
enSocketState mPreSocketState;
enSocketState mSocketState;
ISocketHandler iHandler;
#if UNITY_WEBGL && !UNITY_EDITOR
private WebSocket m_iSocket;
private string m_address;
private bool logMessage = true;
public WebSocket mWebSocket { get { return m_iSocket; } }
public WebSocketState webState { get { return m_iSocket.ReadyState; } }
#endif
float m_fConnectTimeout = 5f;
float m_fBeginConnectTime = -1;
bool m_bConnectExcept = false;
string m_sConnectHost;
int m_iConnectPort;
int mConnectedFrameCount = 0;
public enSocketState State { get { return mSocketState; } }
public Socket Sock { get { return mSocket; } }
public SocketConn(string name = "")
{
mName = name;
mPreSocketState = enSocketState.Disconnected;
mSocketState = enSocketState.Disconnected;
mConnectedFrameCount = 0;
m_bConnectExcept = false;
}
public void RegHandler(ISocketHandler handler)
{
iHandler = handler;
}
public void Resume()
{
mSocketState = enSocketState.ConnectedError;
iHandler.OnError();
}
public void CustomUpdate()
{
if (m_fBeginConnectTime > 0 && Time.realtimeSinceStartup - m_fBeginConnectTime > m_fConnectTimeout)
{
Timeout();
return;
}
if (m_bConnectExcept)
{
Disconnect();
}
if (mSocketState != enSocketState.Connected)
{
return;
}
if (mConnectedFrameCount == 1)
{
mConnectedFrameCount++;
if (iHandler != null)
{
if (mPreSocketState == enSocketState.Reconnecting)
iHandler.OnReconnect();
else
iHandler.OnConnect();
}
}
#if !UNITY_WEBGL || UNITY_EDITOR
try
{
//检测网络是否出错
if (mSocket != null && mSocket.Poll(1, SelectMode.SelectError))
{
if (iHandler != null)
{
try {
mSocketState = enSocketState.ConnectedError;
iHandler.OnError();
}
catch (SocketException se)
{
iHandler.OnException(se);
}
}
}
}
catch (System.Exception ex)
{
Debug.LogError("socket exception: " + ex.Message);
}
#endif
}
/*
连接服务器gate端口规则
1. Editor模式使用ip和固定端口6411
2. WebGL包使用http和ws协议的使用ip和端口6412
3. WebGL包使用https和wss协议的使用域名和固定端口4430
连接服务器serverlist端口规则
1. ip+端口模式:使用端口 6410
2. 域名模式使用https默认端口443
*/
public bool Connect(string host, int port, float timeout = 1f)
{
if (mSocketState != enSocketState.Disconnected)
Disconnect();
mPreSocketState = mSocketState;
mSocketState = enSocketState.Connecting;
m_fConnectTimeout = timeout;
mConnectedFrameCount = 0;
String newServerIp = "";
AddressFamily newAddressFamily = AddressFamily.InterNetwork;
#if UNITY_WEBGL && !UNITY_EDITOR
#else
if (!IPv6SupportMidleware.GetValidServerIpInfo(host, out newServerIp, out newAddressFamily))
{
Debug.LogError("IPv6SupportMidleware is Fail " + host);
Disconnect();
return false;
}
#endif
try
{
#if UNITY_WEBGL && !UNITY_EDITOR
string address = "";
if (CommonUtil.IsValidIPv4(host))
{
address = string.Format("ws://{0}:{1}", host, 6412);
}
else
{
address = string.Format("wss://{0}:{1}", host, 4430);
}
m_address = address;
Debug.LogWarning("Begin connect to Socket Address :" + m_address);
m_iSocket = new WebSocket(m_address);
m_iSocket.OnOpen += Socket_OnOpen;
m_iSocket.OnMessage += Socket_OnMessage;
m_iSocket.OnClose += Socket_OnClose;
m_iSocket.OnError += Socket_OnError;
m_iSocket.ConnectAsync();
mLastIP = host;
mLastPort = port;
m_fBeginConnectTime = Time.realtimeSinceStartup;
#else
// Editor 模式固定端口 6411
port = 6411;
mSocket = new Socket(newAddressFamily, SocketType.Stream, ProtocolType.Tcp);
IPAddress addr = IPAddress.Parse(newServerIp);
IPEndPoint endpoint = new IPEndPoint(addr, port);
Debug.LogWarning("Begin connect to Socket AddressFamily :" + newAddressFamily.ToString() + "ServerIp:" + newServerIp + ", Port:" + port);
mSocket.NoDelay = true;
mSocket.BeginConnect(endpoint, new AsyncCallback(EndConnect), new KeyValuePair<string, int>(host, port));
m_fBeginConnectTime = Time.realtimeSinceStartup;
#endif
return true;
}
catch (SocketException e)
{
Debug.LogError(e.Message);
Disconnect();
}
return false;
}
public bool Reconnect()
{
if (string.IsNullOrEmpty(mLastIP))
throw new Exception("cannot reconnect, last EndPoint is null");
if (mSocketState != enSocketState.Disconnected)
{
Disconnect();
return false;
}
mPreSocketState = mSocketState;
mSocketState = enSocketState.Reconnecting;
mConnectedFrameCount = 0;
String newServerIp = "";
AddressFamily newAddressFamily = AddressFamily.InterNetwork;
#if UNITY_WEBGL && !UNITY_EDITOR
#else
if (!IPv6SupportMidleware.GetValidServerIpInfo(mLastIP, out newServerIp, out newAddressFamily))
{
Debug.LogError("IPv6SupportMidleware is Fail " + mLastIP);
Disconnect();
return false;
}
#endif
try
{
#if UNITY_WEBGL && !UNITY_EDITOR
m_address = string.Format("ws://{0}:{1}", mLastIP, mLastPort);
Debug.LogWarning("Begin connect to Socket Address :" + m_address);
m_iSocket = new WebSocket(m_address);
m_iSocket.OnOpen += Socket_OnOpen;
m_iSocket.OnMessage += Socket_OnMessage;
m_iSocket.OnClose += Socket_OnClose;
m_iSocket.OnError += Socket_OnError;
m_iSocket.ConnectAsync();
m_fBeginConnectTime = Time.realtimeSinceStartup;
#else
mSocket = new Socket(newAddressFamily, SocketType.Stream, ProtocolType.Tcp);
mSocket.NoDelay = true;
Debug.LogWarning("Begin connect to Socket AddressFamily :" + newAddressFamily.ToString() + "ServerIp:" + newServerIp + ", Port:" + mLastPort);
mSocket.BeginConnect(newServerIp, mLastPort, new AsyncCallback(EndConnect), new KeyValuePair<string, int>(newServerIp, mLastPort));
m_fBeginConnectTime = Time.realtimeSinceStartup;
#endif
return true;
}
catch (SocketException e)
{
Debug.LogError(e.Message);
Disconnect();
}
return false;
}
void EndConnect(IAsyncResult async)
{
Debug.Log("Connect AsyncCallback!");
try
{
mSocket.EndConnect(async);
if (mSocketState != enSocketState.Reconnecting)
{
KeyValuePair<string, int> pair = (KeyValuePair<string, int>)async.AsyncState;
mLastIP = pair.Key;
mLastPort = pair.Value;
}
mConnectedFrameCount = 1;
mPreSocketState = mSocketState;
mSocketState = enSocketState.Connected;
}
catch (SocketException e)
{
if (!e.NativeErrorCode.Equals(10035))
{
Debug.LogError(e.Message);
// 当前是异步线程,等待主线程参数判定回调
m_bConnectExcept = true;
}
}
m_fBeginConnectTime = -1f;
}
public void Disconnect(bool ignoreEvent = false)
{
Debug.Log("Disconnect");
#if UNITY_WEBGL && !UNITY_EDITOR
if (m_iSocket != null && m_iSocket.ReadyState != WebSocketState.Closed)
{
mPreSocketState = mSocketState;
mSocketState = enSocketState.Disconnecting;
m_iSocket.CloseAsync();
m_iSocket = null;
}
#else
if (mSocket != null)
{
mPreSocketState = mSocketState;
mSocketState = enSocketState.Disconnecting;
try { mSocket.Shutdown(SocketShutdown.Both); }
catch (SocketException) { }
finally
{
mSocket.Close(0);
mSocket = null;
}
}
#endif
if (!ignoreEvent)
{
if (iHandler != null)
{
iHandler.OnDisconnect();
}
}
mPreSocketState = mSocketState;
mSocketState = enSocketState.Disconnected;
m_fBeginConnectTime = -1f;
mConnectedFrameCount = 0;
m_bConnectExcept = false;
}
private void Timeout()
{
if (iHandler != null)
{
iHandler.OnTimeout();
}
mPreSocketState = mSocketState;
mSocketState = enSocketState.ConnectedTimeout;
m_fBeginConnectTime = -1f;
}
#if UNITY_WEBGL && !UNITY_EDITOR
private void Socket_OnOpen(object sender, OpenEventArgs e)
{
Debug.Log(string.Format("webGl socket Connected: {0}\n", m_address));
mConnectedFrameCount = 1;
mPreSocketState = mSocketState;
mSocketState = enSocketState.Connected;
m_fBeginConnectTime = -1f;
if (iHandler != null)
{
iHandler.OnConnect();
}
}
private void Socket_OnMessage(object sender, MessageEventArgs e)
{
if (e.IsBinary)
{
if (logMessage)
Debug.Log(string.Format("webGl socket Receive Bytes ({1}): {0}\n", e.RawData, e.RawData.Length));
iHandler.webGlMsgUpdate(e.RawData,e.RawData.Length);
}
else if (e.IsText)
{
if (logMessage)
Debug.Log(string.Format("webGl socket Receive: {0}\n", e.Data));
}
}
private void Socket_OnClose(object sender, CloseEventArgs e)
{
Debug.Log(string.Format("webGl socket Closed: StatusCode: {0}, Reason: {1}\n", e.StatusCode, e.Reason));
mPreSocketState = mSocketState;
mSocketState = enSocketState.Disconnected;
m_fBeginConnectTime = -1f;
mConnectedFrameCount = 0;
m_bConnectExcept = false;
}
private void Socket_OnError(object sender, ErrorEventArgs e)
{
Debug.Log(string.Format("webGl socket Error: {0}\n", e.Message));
}
#endif
}