public void Receive(byte[] buffer, out int length, out UnityEngine.Networking.NetworkEventType eventType) { lock (m_queueLock) { if (m_queue.Count == 0) { eventType = NetworkEventType.Nothing; buffer = new byte[0]; length = 0; } else { var frame = m_queue.Dequeue(); length = frame.Length; eventType = frame.LastEventType; System.Buffer.BlockCopy(frame.Buffer, 0, buffer, 0, Mathf.Min(buffer.Length, frame.Length)); } } }
public void ProcessBroadcasts() { int connectionId; int channelId; int receivedSize; byte error; while (m_BroadcastHostId > -1) { UnityEngine.Networking.NetworkEventType ne = NetworkTransport.ReceiveFromHost(m_BroadcastHostId, out connectionId, out channelId, m_Buffer, m_Buffer.Length, out receivedSize, out error); if (ne == UnityEngine.Networking.NetworkEventType.Nothing) { break; } switch (ne) { case UnityEngine.Networking.NetworkEventType.BroadcastEvent: { int _port; string address; NetworkTransport.GetBroadcastConnectionInfo(m_BroadcastHostId, out address, out _port, out error); NetworkTransport.GetBroadcastConnectionMessage(m_BroadcastHostId, m_Buffer, m_Buffer.Length, out receivedSize, out error); var reader = new NetworkReader(m_Buffer, null); int port = reader.ReadInt32(); uint token = reader.ReadUInt32(); string servername = reader.ReadString(); string levelname = reader.ReadString(); string gamemode = reader.ReadString(); int connectedPlayers = reader.ReadInt32(); int maxPlayers = reader.ReadInt32(); if (address.StartsWith("::ffff:")) { address = address.AfterFirst("::ffff:"); } var key = address + ":" + port; ServerInfo si = null; for (var i = 0; i < m_KnownServers.Count; i++) { if (m_KnownServers[i].Address == key) { si = m_KnownServers[i]; break; } } if (si == null) { si = new ServerInfo(); m_KnownServers.Add(si); GameDebug.Log("New server: " + servername + " " + address + ":" + port + " _port: " + _port); } si.Token = token; si.Name = servername; si.LevelName = levelname; si.GameMode = gamemode; si.Players = connectedPlayers; si.MaxPlayers = maxPlayers; si.Address = key; si.LastSeenTime = Time.time; } break; } } for (var i = m_KnownServers.Count - 1; i >= 0; --i) { if (m_KnownServers[i].LastSeenTime < Time.time - 5.0f) { m_KnownServers.RemoveAt(i); } } }
public UdpTransport(bool useUnityThread = false, int queueSize = 16, int maxQueueSize = 34, int port = 12500) { Port = port; // Queue has to be at least 1 large queueSize = Mathf.Max(queueSize, 1); maxQueueSize = Mathf.Max(maxQueueSize, 4); m_nextConnectionId = 0; m_connectionIds = new Dictionary <IPEndPoint, int> (); m_ips = new Dictionary <int, IPEndPoint> (); if (useUnityThread) { } m_udpClient = new UdpClient(Port); m_udpThread = new System.Threading.Thread(new ThreadStart(delegate { while (true) { IPEndPoint remote = null; var buffer = m_udpClient.Receive(ref remote); if (remote == null) { continue; } var isFirstConnection = false; var connectionId = -1; if (!m_connectionIds.ContainsKey(remote)) { m_nextConnectionId++; connectionId = m_nextConnectionId; m_connectionIds [remote] = connectionId; m_ips [connectionId] = remote; isFirstConnection = true; } connectionId = m_connectionIds [remote]; UnityEngine.Networking.NetworkEventType eventType = NetworkEventType.Nothing; if (isFirstConnection) { eventType = NetworkEventType.ConnectEvent; } else { eventType = NetworkEventType.DataEvent; } if (useUnityThread) { lock (m_queueLock) { var frame = new Frame() { LastEventType = eventType, Buffer = buffer, Length = buffer.Length }; // \O(1) but not \Theta(1) time // If we have exceeded our queue size, toss K frames if (m_queue.Count > queueSize) { // Since later frames have redundant input information, we can toss input frames // TODO: We use Tcp for reliable messages // m_queue.Clear (); // In the meantime, inspect the frame and toss input frames if this is an input frame if (buffer.Length > 0 && buffer [0] == MessageType.Input) { // Kill earlier input messages while (m_queue.Count > 0) { var upNext = m_queue.Peek(); if (upNext.Length > 0 && upNext.Buffer [0] == MessageType.Input) { m_queue.Dequeue(); } else { // Clearly a connection or state event got in here... break; } } } if (buffer.Length > 0 && buffer [0] == MessageType.AcknowledgeInput) { // Kill earlier acknowledge input messages while (m_queue.Count > 0) { var upNext = m_queue.Peek(); if (upNext.Length > 0 && upNext.Buffer [0] == MessageType.AcknowledgeInput) { m_queue.Dequeue(); } else { // Clearly a connection or state event got in here... break; } } } } m_queue.Enqueue(frame); if (m_queue.Count > maxQueueSize) { // "Throw an exception" outside of the lock // TODO: Maybe this won't happen that often and memory won't leak. } } } else { if (Received != null) { Received(connectionId, UnreliableChannelId, eventType, buffer, 0, buffer.Length, 0); } } if (m_shouldDisconnect) { break; } } m_udpClient.Close(); })); }