Created
September 9, 2017 10:24
-
-
Save huiliu/bcfae6b9fe15bce12693f29e07597d80 to your computer and use it in GitHub Desktop.
xxxx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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