2021-12-21 09:40:39 +08:00

273 lines
7.7 KiB
C#

using System;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using UnityEngine;
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;
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();
}
}
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);
}
}
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 (!IPv6SupportMidleware.GetValidServerIpInfo(host, out newServerIp, out newAddressFamily))
{
Debug.LogError("IPv6SupportMidleware is Fail " + host);
Disconnect();
return false;
}
try
{
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;
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 (!IPv6SupportMidleware.GetValidServerIpInfo(mLastIP, out newServerIp, out newAddressFamily))
{
Debug.LogError("IPv6SupportMidleware is Fail " + mLastIP);
Disconnect();
return false;
}
try
{
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;
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 (mSocket != null)
{
mPreSocketState = mSocketState;
mSocketState = enSocketState.Disconnecting;
try { mSocket.Shutdown(SocketShutdown.Both); }
catch (SocketException) { }
finally
{
mSocket.Close(0);
mSocket = null;
}
}
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;
}
}