/// <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; } } }
static NUClient() { client = null; m_onConnected = null; m_onConnectionTimeout = null; m_onPacketReceived = null; dataQueue = null; seqDataList = null; broadcastDataQueue = null; hasDisconnected = false; hasConnected = false; dataQueueLock = new object(); seqDataQueueLock = new object(); broadcastDataQueueLock = new object(); multiPartBuffers = null; multiPartLock = new object(); clientComponent = null; broadcaster = null; broadcastServerPort = 0; lastPacketId = -1; }
/// <summary> /// Connect to server on given IP (default loopback) and port (default 25565) /// </summary> /// <param name="address"></param> /// <param name="port"></param> /// <param name="updateHook"></param> public static void Connect(IPAddress address = null, ushort port = 25565, Action updateHook = null, int reservedBufferedPackets = NUUtilities.MaxBufferedPackets) { if (!connected) { //Loopback address if none are given if (address == null) { address = IPAddress.Loopback; } //Create tcpClient TcpClient tcpClient = new TcpClient(AddressFamily.InterNetwork); tcpClient.ReceiveBufferSize = 1048576; //1MB tcpClient.SendBufferSize = 1048576; //1MB Debug.Log("Trying to connect to server at " + address.ToString() + ":" + port); //Initialize data queues dataQueue = new Queue <Packet>(reservedBufferedPackets); seqDataList = new List <Packet>(); lastPacketId = -1; multiPartBuffers = new Dictionary <Hash, MultiPartBuffer>(reservedBufferedPackets, Hash.comparer); //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; } } try { //Begin connecting to server tcpClient.BeginConnect(address, port, new AsyncCallback(EndConnect), tcpClient); } catch (Exception ex) { if (clientComponent != null) { GameObject.DestroyImmediate(clientComponent); } Debug.LogError("Error while connecting to server: " + ex.ToString()); } } else { Debug.LogError("Already Connected to server!"); } }
internal static void ProcessQueues() { m_onBroadcastResponse = NUUtilities.SanitizeAction(m_onBroadcastResponse); m_onConnected = NUUtilities.SanitizeAction(m_onConnected); m_onConnectionFailed = NUUtilities.SanitizeAction(m_onConnectionFailed); m_onDisconnected = NUUtilities.SanitizeAction(m_onDisconnected); m_onServerDisconnected = NUUtilities.SanitizeAction(m_onServerDisconnected); m_onConnectionTimeout = NUUtilities.SanitizeAction(m_onConnectionTimeout); m_onPacketReceived = NUUtilities.SanitizeAction(m_onPacketReceived); if (hasDisconnected) { //Reset flag hasDisconnected = false; bool connectionFailed = !connected; //Destroy client component object if (clientComponent != null) { GameObject.Destroy(clientComponent.gameObject); clientComponent = null; } //Clear dataQueue dataQueue.Clear(); //Clear sequential structures seqDataList.Clear(); lastPacketId = -1; //Clear MultiPart Buffers multiPartBuffers.Clear(); //Disconnect client instance if (client != null) { client.Disconnect(); } //Do proper callbacks if (calledDisconnect) { calledDisconnect = false; if (m_onDisconnected != null) { m_onDisconnected(); } return; } if (serverDisconnected) { serverDisconnected = false; if (m_onServerDisconnected != null) { m_onServerDisconnected(serverDisconnectMsg); } } if (connectionFailed) { if (m_onConnectionFailed != null) { m_onConnectionFailed(); } return; } else { if (m_onConnectionTimeout != null) { m_onConnectionTimeout(); } } } if (hasConnected) { //Reset flag hasConnected = false; //Do proper callback if (m_onConnected != null) { m_onConnected(); } } //Process broadcast callbacks if (broadcaster != null) { //Process broadcast callbacks lock (broadcastDataQueueLock) { while (broadcastDataQueue.Count > 0) { BroadcastPacket packet = broadcastDataQueue.Dequeue(); //Do proper callback if (m_onBroadcastResponse != null) { m_onBroadcastResponse(packet); } } } } if (!connected) { return; } //Process packet callbacks lock (dataQueueLock) { while (dataQueue.Count > 0) { Packet packet = dataQueue.Dequeue(); //Do proper callback if (m_onPacketReceived != null) { m_onPacketReceived(packet); } } } }