Skip to content

Instantly share code, notes, and snippets.

@huiliu
Created September 9, 2017 10:24
Show Gist options
  • Save huiliu/bcfae6b9fe15bce12693f29e07597d80 to your computer and use it in GitHub Desktop.
Save huiliu/bcfae6b9fe15bce12693f29e07597d80 to your computer and use it in GitHub Desktop.
xxxx
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Net.Sockets;
using System.Diagnostics;
using System.Threading;
using YezhStudio.Base;
namespace YezhStudio.ClientLogic
{
// public enum ConnectionStatus
// {
// Connecting = 0,
// Connected = 1,
// Unconnected = 2,
// Closed = 3,
// }
// // 客户端连接对象
// // 这里使用了SocketAsyncEventArgs,它是Begin End模型的一个增强版本,可以对异步过程中创建的异步对象进行复用,
// // 在高并发的场合下,可以节省大量对象重分配,从而实现在高并发吞吐下更少的资源损耗,但使用起来不是特别方便
// // 综上,在客户端中使用SocketAsyncEventArgs可能并不是很合适,可以考虑改为使用更简单的TcpClient
// public class Connection : IDisposable
// {
// public event Action<Connection, bool> OnConnected;
// public event Action<Connection, bool> OnConnectionClosed;
// private int status;
// public ConnectionStatus Status { get; private set; }
// public bool CanSendMore { get { lock (this) return Status == ConnectionStatus.Connected && sendQueue.Count < MAX_SEND_QUEUE_COUNT; } }
// public Connection(string host, int port)
// {
// socket = newSocket();
// isSocketDisposed = false;
// Status = ConnectionStatus.Unconnected;
// inSending = false;
// this.host = host;
// this.port = port;
// connSae = new SocketAsyncEventArgs();
// connSae.Completed += handleConnectCompleted;
// // TODO: 最大包大小
// recvBuffer = new ByteBuffer();
// recvSae = new SocketAsyncEventArgs();
// recvSae.Completed += handleReceiveCompleted;
// eventQueue = new Queue<NetworkEvent>();
// buffer = new byte[0xFFFF + 4];
// sendQueue = new Queue<byte[]>();
// }
// public void Connect()
// {
// //bool result;
// //IPAddress ip;
// //lock (this)
// //{
// // if (Status == ConnectionStatus.Connecting || Status == ConnectionStatus.Connected)
// // return;
// // Status = ConnectionStatus.Connecting;
// // result = IPAddress.TryParse(host, out ip);
// //}
// //if (!result)
// //{
// // ResolveState ioContext = new ResolveState(host);
// // Dns.BeginGetHostEntry(ioContext.host, new AsyncCallback(getHostEntryCallback), ioContext);
// //}
// //else
// //{
// // startConnect(ip);
// //}
// // 状态检查
// var origin = Interlocked.CompareExchange(ref status, (int)ConnectionStatus.Connecting, (int)ConnectionStatus.Unconnected);
// if (origin != (int)ConnectionStatus.Unconnected)
// {
// return;
// }
// // TODO: 考虑IPV6
// IPAddress address;
// if (!IPAddress.TryParse(host, out address))
// {
// try
// {
// // ResolveState resolveState = new ResolveState(host);
// Dns.BeginGetHostEntry(host, new AsyncCallback(getHostEntryCallback), null);
// }
// catch (Exception e)
// {
// shouldBeClose(e);
// }
// }
// else
// {
// startConnect(address);
// }
// }
// public void Close()
// {
// status = (int)ConnectionStatus.Closed;
// onCloseEvent(null);
// }
// private void shouldBeClose(Exception e)
// {
// Trace.WriteLine(string.Format("捕捉到异常!\nMessage: {0}\nStackTrace: {1}\n", e.Message, e.StackTrace));
// Close();
// }
// public void Dispose()
// {
// if (connSae != null) connSae.Dispose();
// if (recvSae != null) recvSae.Dispose();
// throw new NotImplementedException();
// }
// // 重置连接对象
// public void Reset()
// {
// // 关闭原有socket
// if (!isSocketDisposed)
// {
// disposeSocket();
// }
// // 新建一个socket对象用于连接
// socket = newSocket();
// isSocketDisposed = false;
// Status = ConnectionStatus.Unconnected;
// inSending = false;
// }
// public void PeekEvent(Action<int, object> handler)
// {
// while (eventQueue.Count > 0)
// {
// NetworkEvent item;
// lock (this) item = eventQueue.Dequeue();
// handler(item.type, item.data);
// }
// }
// public int GetSendQueueCount()
// {
// if (sendQueue != null)
// return sendQueue.Count;
// return 0;
// }
// // 发送某个消息
// public void Send(byte[] message, bool includeTimestamp = true)
// {
// lock (this)
// {
// // 注意,这里特意不用CanSendMore属性,是为了避免死锁
// if (Status != ConnectionStatus.Connected)
// return;
// if (sendQueue.Count >= MAX_SEND_QUEUE_COUNT)
// {
// Trace.WriteLine(string.Format("snedQueue.Count({0}) >= MAX_SEND_QUEUE_COUNT({1}), will close connection.",
// sendQueue.Count, MAX_SEND_QUEUE_COUNT), "Warning.Connection");
// NetworkCore.Instance.FireOnNeworkBroken();
// // 断线重连
// Close();
// return;
// }
// short dataLen = (short)message.Length;
// short length = (short)(dataLen + (includeTimestamp ? 13 : 5));
// using (MemoryStream ms = new MemoryStream(length))
// {
// BinaryWriter bw = new BinaryWriter(ms);
// bw.Write(NetworkCore.SYNC_MARK_CODE1);
// bw.Write(NetworkCore.SYNC_MARK_CODE2);
// // 时间戳信息
// bw.Write(includeTimestamp);
// if (includeTimestamp)
// bw.Write(Base.Utils.ToTimestamp(TimeService.Instance.LogicTimeNow));
// bw.Write(length);
// bw.Write(message);
// bw.Flush();
//#if UNITY_EDITOR
// // 模拟网络发送延迟
// if (NetworkCore.Instance.FakeNetworkDelay && NetworkCore.Instance.Delay > 0)
// {
// Debug.WriteLine(string.Format("Connection.Send(), FakeNetworkDelay == true, Delay: {0} ms, SetTimer(); timerCount: {1}",
// NetworkCore.Instance.Delay, ++timerCount), "Network");
// Base.PTimer.SetTimer(NetworkCore.Instance.Delay, () =>
// {
// Debug.WriteLine(string.Format("Connection.Send(), timer callback, doneCount: {0}",
// ++doneCount), "Network");
// sendQueue.Enqueue(ms.GetBuffer());
// StartSend();
// }, false, true);
// return;
// }
//#endif
// sendQueue.Enqueue(ms.GetBuffer());
// //Debug.WriteLine(string.Format("Enqueue. sendQueue.Count: {0}, {1}:{2}", sendQueue.Count, DateTime.Now.Second, DateTime.Now.Millisecond));
// StartSend();
// }
// }
// }
// // 开始发送队列中的消息
// public void StartSend()
// {
// if (Status != ConnectionStatus.Connected)
// return;
// if (sendQueue.Count <= 0)
// return;
// if (inSending)
// {
// return;
// }
// if (sendSae != null)
// sendSae.Dispose();
// inSending = true;
// sendSae = new SocketAsyncEventArgs();
// sendSae.Completed += handleSendCompleted;
// doSend();
// }
//#region 保护部分
// private struct NetworkEvent
// {
// public int type;
// public object data;
// }
// private class ResolveState
// {
// string hostName;
// IPHostEntry resolvedIPs;
// public ResolveState(string host)
// {
// hostName = host;
// }
// public IPHostEntry IPs
// {
// get { return resolvedIPs; }
// set { resolvedIPs = value; }
// }
// public string host
// {
// get { return hostName; }
// set { hostName = value; }
// }
// }
// private const int MAX_SEND_QUEUE_COUNT = 500;
// private Socket socket;
// private bool isSocketDisposed;
// private SocketAsyncEventArgs connSae;
// private SocketAsyncEventArgs recvSae;
// private SocketAsyncEventArgs sendSae;
// private ByteBuffer recvBuffer;
// private string host;
// private int port;
// private byte[] buffer;
// private bool inSending;
// private Queue<NetworkEvent> eventQueue;
// private Queue<byte[]> sendQueue;
//#if UNITY_EDITOR
// private static int timerCount = 0;
// private static int doneCount = 0;
//#endif
// private Socket newSocket()
// {
// // TODO: IPV6
// Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
// socket.NoDelay = true;
// return socket;
// }
// // 关闭socket
// private void disposeSocket()
// {
// if (socket.Connected)
// socket.Shutdown(SocketShutdown.Send);
// socket.Close();
// isSocketDisposed = true;
// }
// private void startConnect(IPAddress ip)
// {
// if (status != (int)ConnectionStatus.Connecting)
// {
// return;
// }
// Trace.WriteLine(string.Format("host : {0}, port : {1}", ip, port), "NetworkInfo");
// connSae.RemoteEndPoint = new IPEndPoint(ip, port);
// try
// {
// if (!socket.ConnectAsync(connSae))
// {
// onConnectEvent();
// }
// }
// catch (Exception e)
// {
// // 连接失败
// shouldBeClose(e);
// }
// }
// private void startReceive()
// {
// if (recvSae != null)
// recvSae.Dispose();
// receiveTo(1);
// }
// private void receiveTo(int length)
// {
// var offset = recvSae.Offset + recvSae.BytesTransferred;
// var count = length - offset;
// recvSae.SetBuffer(buffer, offset, count);
// if (!socket.ReceiveAsync(recvSae))
// onReceiveEvent();
// }
// private void getHostEntryCallback(IAsyncResult ar)
// {
// try
// {
// IPHostEntry entries = Dns.EndGetHostEntry(ar);
// startConnect(entries.AddressList[0]);
// }
// catch (Exception e)
// {
// // TODO: 解析DNS失败
// shouldBeClose(e);
// }
// }
// private void onCloseEvent(SocketAsyncEventArgs e)
// {
// NetworkEvent item;
// item.type = NetworkCore.EVENT_CLOSE;
// item.data = e == null ? NetworkCore.CLOSE_BY_SELF : NetworkCore.CLOSE_BY_REMOTE;
// lock (this)
// {
// if (Status == ConnectionStatus.Connected)
// {
// Trace.WriteLine(string.Format("Connection {0}:{1} closed by {2}",
// host, port, e == null ? "self" : "remote"),
// "NetworkInfo");
// eventQueue.Enqueue(item);
// }
// Status = ConnectionStatus.Closed;
// // 清空发送队列
// sendQueue.Clear();
// if (sendSae != null)
// sendSae.Dispose();
// // 关闭socket
// disposeSocket();
// }
// }
// private void onConnectEvent()
// {
// lock (this)
// {
// if (Status == ConnectionStatus.Closed)
// return;
// if (socket.Connected)
// Status = ConnectionStatus.Connected;
// else
// Status = ConnectionStatus.Unconnected;
// NetworkEvent item;
// item.type = NetworkCore.EVENT_OPEN;
// item.data = socket.Connected;
// Trace.WriteLine(String.Format("Connection to {0}:{1} open {2}",
// host, port, socket.Connected ? "successed" : String.Format("failed ({0})", connSae.SocketError.ToString())),
// "NetworkInfo");
// eventQueue.Enqueue(item);
// if (!socket.Connected)
// {
// socket.Shutdown(SocketShutdown.Both);
// socket.Close();
// socket = newSocket();
// }
// if (socket.Connected)
// startReceive();
// }
// }
// private void onReceiveEvent()
// {
// if (recvSae.SocketError != SocketError.Success || recvSae.BytesTransferred <= 0)
// {
// string category = "Connection";
// // Error, connection closed by remote
// if (recvSae.SocketError != SocketError.NotSocket && recvSae.BytesTransferred > 0)
// category = "Error." + category;
// Trace.WriteLine(string.Format("Connection {0}:{1} receive data error {2}", host, port, recvSae.SocketError.ToString()), category);
// if (recvSae.SocketError != SocketError.Success)
// NetworkCore.Instance.FireOnNeworkBroken();
// onCloseEvent(recvSae);
// return;
// }
// var offset = recvSae.Offset;
// offset += recvSae.BytesTransferred;
// if (offset < 1)
// {
// receiveTo(1);
// return;
// }
// else if (offset == 1)
// {
// if (buffer[0] != NetworkCore.SYNC_MARK_CODE1)
// {
// // Bad sync mark, restart receive
// startReceive();
// Trace.WriteLine(String.Format("Connection {0}:{1} receive first byte data, but it is not sync mark 1", host, port), "Error.Connection");
// return;
// }
// receiveTo(2);
// return;
// }
// else if (offset == 2)
// {
// if (buffer[1] != NetworkCore.SYNC_MARK_CODE2)
// {
// // Bad sync mark, restart receive
// Trace.WriteLine(string.Format("Connection {0}:{1} receive second byte data, but it is not sync mark 2", host, port), "Error.Connection");
// startReceive();
// return;
// }
// receiveTo(4);
// return;
// }
// else if (offset < 4)
// {
// receiveTo(4);
// return;
// }
// var length = BitConverter.ToInt16(buffer, 2);
// if (offset < length)
// {
// receiveTo(length);
// return;
// }
// // got a message
// using (MemoryStream ms = new MemoryStream(length - 4))
// {
// BinaryWriter bw = new BinaryWriter(ms);
// bw.Write(buffer, 4, length - 4);
// bw.Flush();
// byte[] message = ms.GetBuffer();
// NetworkEvent item;
// item.type = NetworkCore.EVENT_MESSAGE;
// item.data = message;
// lock (this)
// {
// if (Status != ConnectionStatus.Closed)
// eventQueue.Enqueue(item);
// }
// }
// startReceive();
// }
// private void onSendEvent()
// {
// //Debug.WriteLine("OnSendEvent()");
// if (sendSae.SocketError != SocketError.Success)
// {
// // Error, connection closed by remote
// Trace.WriteLine(string.Format("Connection {0}:{1} send data error: {2}", host, port, sendSae.SocketError.ToString()), "Error.Connection");
// NetworkCore.Instance.FireOnNeworkBroken();
// onCloseEvent(sendSae);
// return;
// }
// lock (this)
// {
// sendQueue.Dequeue();
// if (sendQueue.Count <= 0 || Status != ConnectionStatus.Connected)
// {
// inSending = false;
// return;
// }
// doSend();
// }
// }
// private void doSend()
// {
// byte[] buffer = sendQueue.Peek();
// sendSae.SetBuffer(buffer, 0, buffer.Length);
// if (!socket.SendAsync(sendSae))
// onSendEvent();
// }
// private void handleConnectCompleted(object sender, SocketAsyncEventArgs e)
// {
// onConnectEvent();
// }
// private void handleReceiveCompleted(object sender, SocketAsyncEventArgs e)
// {
// lock (this)
// {
// if (Status == ConnectionStatus.Closed)
// return;
// onReceiveEvent();
// }
// }
// private void handleSendCompleted(object sender, SocketAsyncEventArgs e)
// {
// lock (this)
// {
// //Debug.WriteLine("HandleSendCompleted()");
// if (Status == ConnectionStatus.Closed)
// return;
// onSendEvent();
// }
// }
// #endregion
// }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment