public virtual void Send(uint packetId, object packet) { var cancel = SendHandler.HandlePacket(packetId, packet)?.Cancel ?? false; if (cancel) { return; } var ds = new DataStream { IsLittleEndian = false }; var ok = PacketsRegistry.Serialize(packetId, ds, packet); if (ok) { Send(packetId, ds); SendCompleteHandler.HandlePacket(packetId, packet); } else { Log.Error("Try to send unknown packet {0}", packetId); } }
protected virtual void ConnectWork() { try { if (_Url != null) { bool isMulticastOrBroadcast = false; int port = 0; Uri uri = new Uri(_Url); port = uri.Port; var addresses = Dns.GetHostAddresses(uri.DnsSafeHost); if (addresses != null && addresses.Length > 0) { var address = addresses[0]; if (address.AddressFamily == AddressFamily.InterNetwork) { if (address.Equals(IPAddress.Broadcast)) { isMulticastOrBroadcast = true; } else { var firstb = address.GetAddressBytes()[0]; if (firstb >= 224 && firstb < 240) { isMulticastOrBroadcast = true; } } } else if (address.AddressFamily == AddressFamily.InterNetworkV6) { if (address.IsIPv6Multicast) { isMulticastOrBroadcast = true; } } _Socket = new Socket(address.AddressFamily, SocketType.Dgram, ProtocolType.Udp); if (isMulticastOrBroadcast) { _Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true); if (address.AddressFamily == AddressFamily.InterNetworkV6) { #if NET_STANDARD_2_0 || NET_4_6 // Notice: it is a pitty that unity does not support ipv6 multicast. (Unity 5.6) _Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(address)); _Socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.MulticastTimeToLive, 5); #endif _Socket.Bind(new IPEndPoint(IPAddress.IPv6Any, 0)); } else { if (!address.Equals(IPAddress.Broadcast)) { _Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(address, IPAddress.Any)); _Socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 5); } _Socket.Bind(new IPEndPoint(IPAddress.Any, 0)); } _BroadcastEP = new IPEndPoint(address, port); } else { _Socket.Connect(address, port); } } } if (_Socket != null) { if (_PreStart != null) { _PreStart(this); } byte[] receivebuffer = new byte[CONST.MTU]; int receivecnt = 0; EndPoint broadcastRespEP; if (_BroadcastEP != null && _BroadcastEP.AddressFamily == AddressFamily.InterNetworkV6) { broadcastRespEP = new IPEndPoint(IPAddress.IPv6Any, 0); } else { broadcastRespEP = new IPEndPoint(IPAddress.Any, 0); } Action BeginReceive = () => { if (_BroadcastEP != null) { _Socket.BeginReceiveFrom(receivebuffer, 0, CONST.MTU, SocketFlags.None, ref broadcastRespEP, ar => { try { receivecnt = _Socket.EndReceiveFrom(ar, ref broadcastRespEP); } catch (Exception e) { if (IsConnectionAlive) { _ConnectWorkCanceled = true; PlatDependant.LogError(e); } } _HaveDataToSend.Set(); }, null); } else { _Socket.BeginReceive(receivebuffer, 0, CONST.MTU, SocketFlags.None, ar => { try { receivecnt = _Socket.EndReceive(ar); } catch (Exception e) { if (IsConnectionAlive) { _ConnectWorkCanceled = true; PlatDependant.LogError(e); } } _HaveDataToSend.Set(); }, null); } }; if (_OnReceive != null) { BeginReceive(); } while (!_ConnectWorkCanceled) { if (_OnReceive != null) { if (receivecnt > 0) { if (_BroadcastEP != null && _WaitForBroadcastResp) { _OnReceive(receivebuffer, receivecnt, broadcastRespEP); receivecnt = 0; BeginReceive(); } else { if (_BroadcastEP != null) { _Socket.Connect(broadcastRespEP); _BroadcastEP = null; } _OnReceive(receivebuffer, receivecnt, _Socket.RemoteEndPoint); receivecnt = 0; BeginReceive(); } } } if (!HoldSending) { BufferInfo binfo; while (_PendingSendMessages.TryDequeue(out binfo)) { var message = binfo.Buffer; int cnt = binfo.Count; if (_OnSend != null && _OnSend(message, cnt)) { if (_OnSendComplete != null) { _OnSendComplete(message, true); } } else { SendRaw(message, cnt, success => { if (_OnSendComplete != null) { _OnSendComplete(message, success); } }); } } } if (_OnUpdate != null) { _OnUpdate(this); } var waitinterval = _UpdateInterval; var easeratio = _EaseUpdateRatio; if (waitinterval > 0 && easeratio > 0) { var easeinterval = waitinterval * easeratio; if (_LastSendTick + easeinterval <= System.Environment.TickCount) { waitinterval = easeinterval; } } _HaveDataToSend.WaitOne(waitinterval); } } } catch (ThreadAbortException) { Thread.ResetAbort(); } catch (Exception e) { PlatDependant.LogError(e); } finally { _ConnectWorkRunning = false; _ConnectWorkCanceled = false; if (_PreDispose != null) { _PreDispose(this); } if (_Socket != null) { _Socket.Close(); _Socket = null; } // set handlers to null. _OnReceive = null; _OnSend = null; _OnSendComplete = null; _OnUpdate = null; _PreDispose = null; } }
protected virtual void ConnectWork() { try { PrepareSocket(); if (_Socket != null) { byte[] receivebuffer = new byte[CONST.MTU]; int receivecnt = 0; Action BeginReceive = () => { _Socket.BeginReceive(receivebuffer, 0, 1, SocketFlags.None, ar => { try { receivecnt = _Socket.EndReceive(ar); if (receivecnt > 0) { var bytesRemaining = _Socket.Available; if (bytesRemaining > 0) { if (bytesRemaining > CONST.MTU - 1) { bytesRemaining = CONST.MTU - 1; } receivecnt += _Socket.Receive(receivebuffer, 1, bytesRemaining, SocketFlags.None); } } else { if (_ConnectWorkRunning) { _ConnectWorkCanceled = true; } } } catch (Exception e) { if (IsConnectionAlive) { _ConnectWorkCanceled = true; PlatDependant.LogError(e); } } _HaveDataToSend.Set(); }, null); }; BeginReceive(); while (!_ConnectWorkCanceled) { if (receivecnt > 0) { if (_OnReceive != null) { _OnReceive(receivebuffer, receivecnt, _Socket.RemoteEndPoint); } receivecnt = 0; BeginReceive(); } BufferInfo binfo; while (_PendingSendMessages.TryDequeue(out binfo)) { var message = binfo.Buffer; int cnt = binfo.Count; if (_OnSend != null && _OnSend(message, cnt)) { if (_OnSendComplete != null) { _OnSendComplete(message, true); } } else { SendRaw(message, cnt, success => { if (_OnSendComplete != null) { _OnSendComplete(message, success); } }); } } _HaveDataToSend.WaitOne(); } _Socket.Shutdown(SocketShutdown.Both); } } catch (ThreadAbortException) { Thread.ResetAbort(); } catch (Exception e) { PlatDependant.LogError(e); } finally { _ConnectWorkRunning = false; _ConnectWorkCanceled = false; if (_PreDispose != null) { _PreDispose(this); } if (_Socket != null) { _Socket.Close(); _Socket = null; } // set handlers to null. _OnReceive = null; _OnSend = null; _OnSendComplete = null; _PreDispose = null; } }