391 lines
12 KiB
C#
391 lines
12 KiB
C#
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
|
||
}
|