337 lines
10 KiB
C#
337 lines
10 KiB
C#
/*
|
||
********************************************************************************
|
||
*Copyright(C),coolae.net
|
||
*Author: chenbin
|
||
*Version: 2.0
|
||
*Date: 2017-01-09
|
||
*Description: socke,封装c# socketNumber据传输协议
|
||
*Others:
|
||
*History:
|
||
*********************************************************************************
|
||
*/
|
||
using UnityEngine;
|
||
using System;
|
||
using System.IO;
|
||
using System.Net;
|
||
using System.Net.Sockets;
|
||
using System.Collections;
|
||
using System.Text;
|
||
using System.Threading;
|
||
|
||
namespace Coolape
|
||
{
|
||
#if !UNITY_WEBGL
|
||
public delegate void NetCallback(USocket socket, object obj);
|
||
public delegate void OnReceiveCallback(USocket socket, byte[] bytes, int len);
|
||
|
||
public class USocket
|
||
{
|
||
public string host;
|
||
public int port;
|
||
public Socket mSocket;
|
||
public static int mTmpBufferSize = 64 * 1024;
|
||
public byte[] mTmpBuffer = null;
|
||
private IPEndPoint ipe;
|
||
private NetCallback onConnectStateChgCallback;
|
||
private OnReceiveCallback onReceiveCallback;
|
||
private int failTimes = 0;
|
||
private bool isClosed = false;
|
||
public bool isActive = false;
|
||
public Timer timeoutCheckTimer;
|
||
public enum Errors
|
||
{
|
||
success = 0,
|
||
connectTimeout = 1,
|
||
IPEndPointIsNull = 2,
|
||
connectFailed = 3,
|
||
receivebytesLenError = 4,
|
||
serverClosedConnection = 5,
|
||
connectionIsClosed = 6,
|
||
sendAsynException = 7,
|
||
sendTimeout = 8,
|
||
}
|
||
|
||
public USocket(string host, int port)
|
||
{
|
||
init(host, port);
|
||
}
|
||
|
||
public void init(string host, int port)
|
||
{
|
||
isClosed = false;
|
||
this.host = host;
|
||
this.port = port;
|
||
IPAddress ip = null;
|
||
try
|
||
{
|
||
// is ip xx.xx.xx.xx
|
||
ip = IPAddress.Parse(host);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
// may be is dns
|
||
try
|
||
{
|
||
IPAddress[] address = Dns.GetHostAddresses(host);
|
||
if (address.Length > 0)
|
||
{
|
||
ip = address[0];
|
||
}
|
||
}
|
||
catch (Exception e2)
|
||
{
|
||
Debug.LogError(e2);
|
||
return;
|
||
}
|
||
}
|
||
if (ip == null)
|
||
{
|
||
Debug.LogError("Get ip is null");
|
||
return;
|
||
}
|
||
ipe = new IPEndPoint(ip, port);
|
||
|
||
if (ip.AddressFamily == AddressFamily.InterNetworkV6)
|
||
{
|
||
Debug.LogWarning("is ipv6");
|
||
mSocket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
|
||
}
|
||
else
|
||
{
|
||
Debug.LogWarning("is ipv4");
|
||
mSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||
}
|
||
|
||
if (mTmpBuffer == null)
|
||
{
|
||
mTmpBuffer = new byte[mTmpBufferSize];
|
||
}
|
||
}
|
||
|
||
// 异步模式//////////////////////////////////////////////////////////////////
|
||
// 异步模式//////////////////////////////////////////////////////////////////
|
||
//public bool IsConnectionSuccessful = false;
|
||
public int timeoutMSec = 5000; //毫秒
|
||
public int maxTimeoutTimes = 3;
|
||
Timer connectTimeout = null;
|
||
|
||
public void connectAsync(NetCallback onConnectStateChgCallback)
|
||
{
|
||
try
|
||
{
|
||
isActive = false;
|
||
this.onConnectStateChgCallback = onConnectStateChgCallback;
|
||
if (ipe == null)
|
||
{
|
||
onConnectStateChg(false, Errors.IPEndPointIsNull);
|
||
return;
|
||
}
|
||
|
||
mSocket.BeginConnect(ipe, (AsyncCallback)connectCallback, this);
|
||
if (connectTimeout != null)
|
||
{
|
||
connectTimeout.Dispose();
|
||
connectTimeout = null;
|
||
}
|
||
connectTimeout = TimerEx.schedule((TimerCallback)connectTimeOut, null, timeoutMSec);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
}
|
||
|
||
void connectTimeOut(object orgs)
|
||
{
|
||
if (isActive)
|
||
{
|
||
}
|
||
else
|
||
{
|
||
onConnectStateChg(false, Errors.connectTimeout);
|
||
}
|
||
}
|
||
|
||
protected void onConnectStateChg(bool connected, Errors retCode)
|
||
{
|
||
string msg = Enum.GetName(typeof(Errors), retCode);
|
||
Debug.LogWarning("connected=[" + connected + "]" + " retCode=[" + (int)retCode + "]" + " msg=[" + msg +"]");
|
||
if (isClosed)
|
||
{
|
||
return;
|
||
}
|
||
if (!connected && isActive)
|
||
{
|
||
if (retCode == Errors.serverClosedConnection)
|
||
{
|
||
close();
|
||
}
|
||
}
|
||
if (this.onConnectStateChgCallback != null)
|
||
{
|
||
ArrayList list = new ArrayList();
|
||
list.Add(connected);
|
||
list.Add((int)(retCode));
|
||
list.Add(msg);
|
||
this.onConnectStateChgCallback(this, list);
|
||
}
|
||
}
|
||
|
||
private void connectCallback(IAsyncResult ar)
|
||
{
|
||
// 从stateobject获取socket.
|
||
USocket client = (USocket)ar.AsyncState;
|
||
if (client.mSocket.Connected)
|
||
{
|
||
// 完成连接.
|
||
client.mSocket.EndConnect(ar);
|
||
client.isActive = true;
|
||
client.failTimes = 0;
|
||
client.onConnectStateChg(true, Errors.success);
|
||
}
|
||
else
|
||
{
|
||
client.onConnectStateChg(false, Errors.connectFailed);
|
||
}
|
||
if (connectTimeout != null)
|
||
{
|
||
connectTimeout.Dispose();
|
||
connectTimeout = null;
|
||
}
|
||
}
|
||
|
||
public void close()
|
||
{
|
||
try
|
||
{
|
||
isClosed = true;
|
||
isActive = false;
|
||
failTimes = 0;
|
||
if (mSocket != null)
|
||
{
|
||
mSocket.Close();
|
||
}
|
||
mSocket = null;
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
}
|
||
|
||
public void ReceiveAsync(OnReceiveCallback callback)
|
||
{
|
||
onReceiveCallback = callback;
|
||
ReceiveAsync();
|
||
}
|
||
|
||
private void ReceiveAsync()
|
||
{
|
||
try
|
||
{
|
||
// 从远程target接收Number据.
|
||
mSocket.BeginReceive(mTmpBuffer, 0, mTmpBufferSize, 0,
|
||
(AsyncCallback)ReceiveCallback, this);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError(e);
|
||
}
|
||
}
|
||
|
||
private void ReceiveCallback(IAsyncResult ar)
|
||
{
|
||
USocket client = (USocket)ar.AsyncState;
|
||
try
|
||
{
|
||
if (client.timeoutCheckTimer != null)
|
||
{
|
||
client.timeoutCheckTimer.Dispose();
|
||
client.timeoutCheckTimer = null;
|
||
}
|
||
if (client.isActive)
|
||
{
|
||
client.failTimes = 0;
|
||
//从远程设备读取Number据
|
||
int bytesRead = client.mSocket.EndReceive(ar);
|
||
if (bytesRead > 0)
|
||
{
|
||
//Debug.Log("receive len==" + bytesRead);
|
||
// 有Number据,存储.
|
||
onReceiveCallback(client, client.mTmpBuffer, bytesRead);
|
||
}
|
||
else if (bytesRead < 0)
|
||
{
|
||
client.onConnectStateChg(false, Errors.receivebytesLenError);
|
||
}
|
||
else
|
||
{
|
||
// 所有Number据读取完毕.
|
||
Debug.Log("receive zero=====" + bytesRead);
|
||
client.onConnectStateChg(false, Errors.serverClosedConnection);
|
||
return;
|
||
}
|
||
|
||
// 继续读取.
|
||
client.ReceiveAsync();
|
||
}
|
||
else
|
||
{
|
||
client.onConnectStateChg(false, Errors.connectionIsClosed);
|
||
}
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.Log(e);
|
||
}
|
||
}
|
||
|
||
public void SendAsync(byte[] data)
|
||
{
|
||
try
|
||
{
|
||
if (data == null)
|
||
return;
|
||
// isOpen始发送Number据到远程设备.
|
||
if (this.timeoutCheckTimer == null)
|
||
{
|
||
this.timeoutCheckTimer = TimerEx.schedule((TimerCallback)sendTimeOut, null, timeoutMSec);
|
||
}
|
||
|
||
mSocket.BeginSend(data, 0, data.Length, 0,
|
||
(AsyncCallback)SendCallback, this);
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
Debug.LogError("socket:" + e);
|
||
onConnectStateChg(false, Errors.sendAsynException);
|
||
}
|
||
}
|
||
|
||
public void sendTimeOut(object orgs)
|
||
{
|
||
failTimes++;
|
||
if (failTimes > maxTimeoutTimes)
|
||
{
|
||
onConnectStateChg(false, Errors.sendTimeout);
|
||
}
|
||
}
|
||
|
||
private void SendCallback(IAsyncResult ar)
|
||
{
|
||
USocket client = (USocket)ar.AsyncState;
|
||
// 完成Number据发送.
|
||
int bytesSent = client.mSocket.EndSend(ar);
|
||
if (bytesSent <= 0) //发送失败
|
||
{
|
||
sendTimeOut(null);
|
||
}
|
||
else
|
||
{
|
||
client.failTimes = 0;
|
||
}
|
||
}
|
||
|
||
}
|
||
#endif
|
||
} |