//When finished broadcast send private static void EndBroadcastSend(IAsyncResult asyncResult) { //Extract UnreliableTransmissionState from Async State BroadcastTransmissionState transmissionState = (BroadcastTransmissionState)asyncResult.AsyncState; Socket broadcaster = transmissionState.broadcaster; try { broadcaster.EndSend(asyncResult); //Callback of transmission state if (transmissionState.callback != null) { transmissionState.callback(); } } catch (Exception ex) { if (ex.GetType() == typeof(ObjectDisposedException) || broadcaster == null || !broadcaster.IsBound) { return; } Debug.LogError("Error sending unreliable packet to server: " + ex); } }
/// <summary> /// Setup the broadcast channel for the given adapter address and port. /// </summary> /// <param name="adapterAddress">The Network Adapter address to be used for broadcasting. /// See <see cref="NUUtilities.ListIPv4Addresses()"/> for valid sources.</param> /// <param name="broadcastPort">The port in which the broadcast will happen.</param> public static void SetupBroadcast(IPAddress adapterAddress = null, ushort broadcastServerPort = 56552, Action updateHook = null, int reservedBufferedPackets = NUUtilities.MaxBufferedPackets) { //Loopback address if none are given if (adapterAddress == null) { adapterAddress = IPAddress.Loopback; } NUClient.broadcastServerPort = broadcastServerPort; // Setup broadcast ranges and receiving queue IPAddress subnet = NUUtilities.GetSubnetMaskFromIPv4(adapterAddress); UInt32 subnetInt = NUUtilities.GetUIntFromIpAddress(subnet); UInt32 addressInt = NUUtilities.GetUIntFromIpAddress(adapterAddress); broadcastStartRange = (addressInt & subnetInt) + 1; broadcastFinalRange = (addressInt | (~subnetInt)) - 1; lock (broadcastDataQueueLock) { broadcastDataQueue = new Queue <BroadcastPacket>(reservedBufferedPackets); } IPEndPoint broadcastEp = new IPEndPoint(adapterAddress, 0); broadcaster = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) { ExclusiveAddressUse = true }; broadcaster.Bind(broadcastEp); BroadcastTransmissionState broadcastState = new BroadcastTransmissionState( NUUtilities.MTU, ref broadcaster, null); EndPoint broadcastSenderEp = broadcastState.senderEp; broadcaster.BeginReceiveFrom(broadcastState.data, 0, NUUtilities.MTU, SocketFlags.None, ref broadcastSenderEp, new AsyncCallback(EndBroadcastReceive), broadcastState); //Hook on updateHook otherwise instantiate NUClientComponent if (updateHook != null) { updateHook += ProcessQueues; } else { //Create MonoBehaviour instance if it doesn't exists if (clientComponent == null) { GameObject clientObject = new GameObject("NUClientObject"); //clientObject.hideFlags = HideFlags.HideAndDontSave; GameObject.DontDestroyOnLoad(clientObject); clientComponent = clientObject.AddComponent <NUClientComponent>(); //clientObject.hideFlags = HideFlags.HideInInspector; } } }
private static void EndBroadcastReceive(IAsyncResult asyncResult) { //Extract UDPClient from Async State BroadcastTransmissionState broadcastState = (BroadcastTransmissionState)asyncResult.AsyncState; Socket broadcaster = broadcastState.broadcaster; try { //End receiving data int receivedSize = broadcaster.EndReceiveFrom(asyncResult, ref broadcastState.senderEp); if (receivedSize > 0) { //Get Message flag and process accordingly Packet receivedPacket = new Packet(broadcastState.data, receivedSize); //Ignore packets that are not valid in our broadcast routines if (receivedPacket.flag == Packet.TypeFlag.BROADCAST) { BroadcastPacket broadcastPacket = new BroadcastPacket(receivedPacket, (IPEndPoint)broadcastState.senderEp); lock (broadcastDataQueueLock) { broadcastDataQueue.Enqueue(broadcastPacket); } } } //Keep receiving data broadcaster.BeginReceiveFrom(broadcastState.data, 0, NUUtilities.MTU, SocketFlags.None, ref broadcastState.senderEp, new AsyncCallback(EndBroadcastReceive), broadcastState); } catch (Exception ex) { if (ex.GetType() == typeof(ObjectDisposedException) || broadcaster == null || !broadcaster.IsBound) { return; } Debug.LogError("Error occurred receiving broadcast packet: " + ex.Message); //Keep receiving data (because one connection error should not eliminate other responses) broadcaster.BeginReceiveFrom(broadcastState.data, 0, NUUtilities.MTU, SocketFlags.None, ref broadcastState.senderEp, new AsyncCallback(EndBroadcastReceive), broadcastState); } }
/// <summary> /// Broadcast a Packet (whose destination doesn't matter) /// </summary> /// <param name="emptyDestinationPacket">An packet whose destination doesn't matter</param> public static void Broadcast(Packet emptyDestinationPacket, Action callback = null) { if (broadcaster == null) { Debug.LogWarning("Broadcast not configured! Using default settings...\n" + "Call NUClient.SetupBroadcast() with corrent parameters."); SetupBroadcast(); } if (emptyDestinationPacket.data == null) { Debug.LogError("Data to be sent is null!"); return; } if (emptyDestinationPacket.data.Length == 0) { Debug.LogError("Data to be sent is empty!"); return; } // Set Broadcast Flag if not already if (emptyDestinationPacket.flag != Packet.TypeFlag.BROADCAST) { emptyDestinationPacket.OverridePacketFlag(Packet.TypeFlag.BROADCAST); } BroadcastTransmissionState transmissionState = new BroadcastTransmissionState( emptyDestinationPacket.data.Length, ref broadcaster, callback); // Send a broadcast transmission to the full range of IPs range IPEndPoint receivingEp = (IPEndPoint)broadcaster.LocalEndPoint; for (uint ip = broadcastStartRange + 1; ip < broadcastFinalRange; ip++) { IPAddress broadcastIp = NUUtilities.GetIpAddressFromUInt32(ip); IPEndPoint broadcastEp = new IPEndPoint(broadcastIp, broadcastServerPort); broadcaster.BeginSendTo(emptyDestinationPacket.data, 0, emptyDestinationPacket.data.Length, SocketFlags.None, broadcastEp, new AsyncCallback(EndBroadcastSend), transmissionState); } }