You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
241 lines
7.3 KiB
241 lines
7.3 KiB
3 years ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Text;
|
||
|
using System.IO;
|
||
|
using System.Net.Sockets;
|
||
|
|
||
|
namespace ILRuntime.Runtime.Debugger
|
||
|
{
|
||
|
public class DebugSocket
|
||
|
{
|
||
|
private Socket _socket = null;
|
||
|
private bool _ready = false;
|
||
|
private const int MAX_BUFF_SIZE = 256 * 1024;
|
||
|
private const int HEAD_SIZE = 8;
|
||
|
private byte[] _headBuffer = new byte[HEAD_SIZE];
|
||
|
private byte[] _sendBuffer = new byte[64 * 1024];
|
||
|
//private MemoryPoolSafe<Package> _packagePool = new MemoryPoolSafe<Package>();
|
||
|
//private Package _currPackage = null;
|
||
|
private System.IO.MemoryStream _sendStream = null;
|
||
|
BinaryWriter bw;
|
||
|
const int RECV_BUFFER_SIZE = 1024;
|
||
|
private MemoryStream recvBuffer = new MemoryStream();
|
||
|
private int lastMsgLength = -1;
|
||
|
|
||
|
private byte[] socketAsyncBuffer = new byte[RECV_BUFFER_SIZE];
|
||
|
private SocketAsyncEventArgs saeArgs;
|
||
|
private object socketLockObj = new object();
|
||
|
private byte[] _sendHeaderBuffer = new byte[HEAD_SIZE];
|
||
|
|
||
|
public bool Disconnected { get { return _socket == null || !_socket.Connected; } }
|
||
|
public Action OnConnect { get; set; }
|
||
|
|
||
|
public Action OnConnectFailed { get; set; }
|
||
|
public Action OnClose { get; set; }
|
||
|
|
||
|
public Action<DebugMessageType, byte[]> OnReciveMessage { get; set; }
|
||
|
|
||
|
|
||
|
public DebugSocket()
|
||
|
{
|
||
|
_sendStream = new System.IO.MemoryStream(_sendBuffer);
|
||
|
bw = new BinaryWriter(_sendStream);
|
||
|
}
|
||
|
public DebugSocket(Socket _socket)
|
||
|
: this()
|
||
|
{
|
||
|
this._socket = _socket;
|
||
|
BeginReceive();
|
||
|
_ready = true;
|
||
|
}
|
||
|
public void Connect(string ip, int port)
|
||
|
{
|
||
|
Close();
|
||
|
Socket socket;
|
||
|
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||
|
socket.BeginConnect(ip, port, new AsyncCallback(onConnected), this);
|
||
|
_socket = socket;
|
||
|
_ready = false;
|
||
|
}
|
||
|
|
||
|
private void AsyncRecv_Completed(object sender, SocketAsyncEventArgs e)
|
||
|
{
|
||
|
if (e.SocketError == SocketError.Success && e.BytesTransferred > 0)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
ReceivePayload(e.Buffer, e.BytesTransferred);
|
||
|
}
|
||
|
catch (Exception)
|
||
|
{
|
||
|
Close();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
Close();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
//继续接受数据
|
||
|
if (!_socket.ReceiveAsync(saeArgs))
|
||
|
{
|
||
|
AsyncRecv_Completed(null, saeArgs);
|
||
|
}
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
Close();
|
||
|
throw ex;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void ReceivePayload(byte[] data, int length)
|
||
|
{
|
||
|
if (_socket == null)
|
||
|
return;
|
||
|
if (!_socket.Connected)
|
||
|
{
|
||
|
Close();
|
||
|
return;
|
||
|
}
|
||
|
//接受数据并拼接成message
|
||
|
byte[] msgBuff;
|
||
|
//写入缓存
|
||
|
recvBuffer.Position = recvBuffer.Length;
|
||
|
recvBuffer.Write(data, 0, length);
|
||
|
//如果长度有错,返回
|
||
|
if (lastMsgLength < 0 && recvBuffer.Length < 4)
|
||
|
{
|
||
|
msgBuff = null;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
recvBuffer.Position = 0;
|
||
|
BinaryReader br = new BinaryReader(recvBuffer);
|
||
|
//读取消息长度
|
||
|
if (lastMsgLength < 0)
|
||
|
{
|
||
|
lastMsgLength = br.ReadInt32() - 4;
|
||
|
if (lastMsgLength > MAX_BUFF_SIZE)
|
||
|
{
|
||
|
Close();
|
||
|
throw new Exception("Too long package length!");
|
||
|
}
|
||
|
}
|
||
|
int remaining = (int)(recvBuffer.Length - recvBuffer.Position);
|
||
|
//消息已经完整
|
||
|
while (remaining >= lastMsgLength && lastMsgLength > 0)
|
||
|
{
|
||
|
|
||
|
//读取一条消息
|
||
|
int type = br.ReadInt32();
|
||
|
msgBuff = br.ReadBytes(lastMsgLength - 4);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
if (OnReciveMessage != null)
|
||
|
OnReciveMessage((DebugMessageType)type, msgBuff);
|
||
|
}
|
||
|
catch(Exception ex)
|
||
|
{
|
||
|
Console.WriteLine(ex.ToString());
|
||
|
}
|
||
|
lastMsgLength = -1;
|
||
|
remaining = (int)(recvBuffer.Length - recvBuffer.Position);
|
||
|
//保留剩余数据
|
||
|
if (remaining >= 4)
|
||
|
{
|
||
|
lastMsgLength = br.ReadInt32() - 4;
|
||
|
remaining -= 4;
|
||
|
if (lastMsgLength > MAX_BUFF_SIZE)
|
||
|
{
|
||
|
Close();
|
||
|
throw new Exception("Too long package length!");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
remaining = (int)(recvBuffer.Length - recvBuffer.Position);
|
||
|
if (remaining > 0)
|
||
|
{
|
||
|
byte[] buffer = recvBuffer.GetBuffer();
|
||
|
Array.Copy(buffer, recvBuffer.Position, buffer, 0, remaining);
|
||
|
}
|
||
|
recvBuffer.Position = 0;
|
||
|
recvBuffer.SetLength(remaining);
|
||
|
}
|
||
|
private void onConnected(IAsyncResult result)
|
||
|
{
|
||
|
if (_socket.Connected)
|
||
|
{
|
||
|
_socket.EndConnect(result);
|
||
|
|
||
|
BeginReceive();
|
||
|
if (OnConnect != null)
|
||
|
OnConnect();
|
||
|
//ReceiveOnce();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (OnConnectFailed != null)
|
||
|
OnConnectFailed();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void BeginReceive()
|
||
|
{
|
||
|
saeArgs = new SocketAsyncEventArgs();
|
||
|
saeArgs.Completed += AsyncRecv_Completed;
|
||
|
saeArgs.SetBuffer(socketAsyncBuffer, 0, socketAsyncBuffer.Length);
|
||
|
_socket.ReceiveAsync(saeArgs);
|
||
|
_ready = true;
|
||
|
}
|
||
|
|
||
|
//len type msg
|
||
|
public void Send(DebugMessageType type, byte[] buffer, int len)
|
||
|
{
|
||
|
if (!_ready)
|
||
|
return;
|
||
|
|
||
|
//timeStamp = UnityEngine.Time.realtimeSinceStartup;
|
||
|
_sendStream.Position = 0;
|
||
|
bw.Write(len + HEAD_SIZE);
|
||
|
bw.Write((int)type);
|
||
|
bw.Write(buffer, 0, len);
|
||
|
int totalLen = (int)_sendStream.Position;
|
||
|
|
||
|
RawSend(_socket, _sendBuffer, totalLen);
|
||
|
//_socket.Send(_sendBuffer, len, SocketFlags.None);
|
||
|
}
|
||
|
|
||
|
private void RawSend(Socket sock, byte[] buf, int end)
|
||
|
{
|
||
|
if (sock == null)
|
||
|
return;
|
||
|
if (end < 0)
|
||
|
end = buf.Length;
|
||
|
sock.Send(buf, end, SocketFlags.None);
|
||
|
}
|
||
|
|
||
|
public void Close()
|
||
|
{
|
||
|
if (_socket == null || !_ready)
|
||
|
return;
|
||
|
if (saeArgs != null)
|
||
|
saeArgs.Dispose();
|
||
|
_socket.Close();
|
||
|
_socket = null;
|
||
|
_ready = false;
|
||
|
if (OnClose != null)
|
||
|
{
|
||
|
OnClose();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|