void SendUdpControl(SocketNetDriverConnection connection) { controlCodeBytes[0] = (byte)EControlCode.SetChannelID; controlCodeBytes[1] = (byte)(connection.channelID & 0xff); controlCodeBytes[2] = (byte)((connection.channelID >> 8) & 0xff); connection.SendUnreliable(controlCodeBytes, 3); }
internal void ReliableSendWouldBlock(SocketNetDriverConnection connection) { if (_serverCallbacks != null) { _serverCallbacks.OnReliableSendWouldBlock(connection); } if (_clientCallbacks != null) { _clientCallbacks.OnReliableSendWouldBlock(connection); } }
public bool Connect(string address, int port, INetDriverCallbacks callbacks) { if (address == "localhost") { address = "127.0.0.1"; } var serverIP = GetIPAddressFromString(address); if (serverIP == null) { Debug.LogError("Could not resolve " + address); return(false); } _clientCallbacks = callbacks; var serverEndPoint = new IPEndPoint(serverIP, port); var clientSocks = new Socket[2]; clientSocks[0] = new Socket(serverEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); clientSocks[1] = new Socket(serverEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp); try { clientSocks[0].NoDelay = true; clientSocks[0].SendTimeout = 500; clientSocks[0].ReceiveBufferSize = World.MAX_RELIABLE_MESSAGE_SIZE; clientSocks[1].SendBufferSize = World.MAX_UNRELIABLE_MESSAGE_SIZE * 4; clientSocks[1].ReceiveBufferSize = World.MAX_UNRELIABLE_MESSAGE_SIZE * 4; clientSocks[1].DisableICMPUnreachablePortError(); Debug.Log("Connecting to " + serverEndPoint.Address.ToString()); clientSocks[0].Connect(serverEndPoint); clientSocks[1].Bind(new IPEndPoint(IPAddress.Any, 0)); Debug.Log("Connected to " + serverEndPoint.Address.ToString()); _serverConnection = new SocketNetDriverConnection(this, clientSocks, -1); _serverConnection.udpEndpoint = clientSocks[0].RemoteEndPoint; } catch (Exception e) { Debug.LogException(e); return(false); } return(true); }
internal void ConnectionDisposed(SocketNetDriverConnection connection) { if (connection == _serverConnection) { try { connection.sockets[1].Close(); } catch (Exception) {} _serverConnection = null; if ((_clientCallbacks != null) && connection.didHandshake) { _clientCallbacks.OnDisconnect(connection); } } else { bool r = _tcpConnections.Remove(connection.tcpEndpoint); Assert.IsTrue(r); if (connection.udpEndpoint != null) { r = _udpConnections.Remove(connection.udpEndpoint); Assert.IsTrue(r); } if ((_serverCallbacks != null) && connection.didHandshake) { _serverCallbacks.OnDisconnect(connection); } } try { connection.sockets[0].Close(); } catch (Exception) { } connection.sockets[0] = null; connection.sockets[1] = null; }
public void TickServer(float dt, byte[] recvBuffer, ref NetIOMetrics reliableChannelMetrics, ref NetIOMetrics unreliableChannelMetrics) { Perf.Begin("SocketNetDriver.TickServer"); for (;;) { Socket newSocket; try { newSocket = _serverSock[0].Accept(); } catch (SocketException) { break; } if (_tcpConnections.ContainsKey(newSocket.RemoteEndPoint)) { Debug.LogError("Connection attempt from already connected client!"); newSocket.Close(); continue; } var clientSocks = new Socket[2]; clientSocks[0] = newSocket; clientSocks[1] = _serverSock[1]; newSocket.Blocking = false; //newSocket.NoDelay = true; newSocket.SendBufferSize = World.MAX_RELIABLE_MESSAGE_SIZE * 8; newSocket.SendTimeout = 500; var newConn = new SocketNetDriverConnection(this, clientSocks, nextChannelID++); _tcpConnections.Add(newSocket.RemoteEndPoint, newConn); SendTcpControl(newConn); } for (int i = 0; i < _tcpConnections.Values.Count;) { var c = _tcpConnections.Values[i]; bool wasReset = false; bool isDisposed = false; try { wasReset = c.sockets[0].Poll(0, SelectMode.SelectRead); } catch (Exception) { isDisposed = true; } if (isDisposed || (wasReset && (c.sockets[0].Available == 0))) { c.Dispose(); continue; } Recv(c, _serverCallbacks, c.sockets[0], recvBuffer, ref reliableChannelMetrics, false); if (c.isValid && !c.didHandshake) { c.handshakeTime += dt; if (c.handshakeTime > UDP_CONTROL_DISCONNECT_TIMEOUT) { // handshake failed Debug.LogError("Disconnecting " + c.tcpEndpoint.ToString() + ": udp handshake timed out"); c.Dispose(); } } if (c.isValid) { ++i; } } RecvFrom(_serverCallbacks, _serverSock[1], recvBuffer, ref unreliableChannelMetrics); Perf.End(); }
void Recv(SocketNetDriverConnection connection, INetDriverCallbacks callbacks, Socket socket, byte[] buffer, ref NetIOMetrics metrics, bool isDatagram) { Perf.Begin("SocketNetDriver.Recv"); if (isDatagram) { while (connection.isValid && (socket.Available > 0)) { int r; try { r = socket.Receive(buffer, 0, World.MAX_UNRELIABLE_MESSAGE_SIZE, SocketFlags.None); if (r <= 0) { throw new SocketException((int)SocketError.SocketError); } metrics.bytesRecv += r; ++metrics.numPacketsRecv; } catch (Exception e) { Debug.LogException(e); callbacks.OnInvalidMessageReceived(connection); continue; } if (!connection.didHandshake) { // client may receive a UDP packet before receiving control ACK // so discard the packet until we process the ACK. continue; } callbacks.OnMessageReceived(connection, buffer, r); } } else { while (connection.isValid && (socket.Available > 0)) { if (connection.pendingRecvSize <= 0) { if (socket.Available < 2) { break; } // read from socket. if (socket.Receive(connection.pendingBytes, 0, 2, SocketFlags.None) != 2) { throw new SocketException((int)SocketError.SocketError); } connection.pendingRecvSize = ((int)connection.pendingBytes[0]) | (((int)connection.pendingBytes[1]) << 8); connection.pendingBytesReceived = 0; if (connection.pendingRecvSize > connection.pendingBytes.Length) { callbacks.OnInvalidMessageReceived(connection); continue; } } { // read from socket. var numBytesToRead = Mathf.Min(socket.Available, connection.pendingRecvSize - connection.pendingBytesReceived); if (numBytesToRead > 0) { if (socket.Receive(connection.pendingBytes, connection.pendingBytesReceived, numBytesToRead, SocketFlags.None) != numBytesToRead) { throw new SocketException((int)SocketError.SocketError); } connection.pendingBytesReceived += numBytesToRead; } } Assert.IsTrue(connection.pendingBytesReceived <= connection.pendingRecvSize); if (connection.pendingBytesReceived >= connection.pendingRecvSize) { if (!connection.didHandshake) { if (callbacks == _clientCallbacks) { if (connection.channelID == -1) { var id = RecvControl(connection.pendingBytes, connection.pendingRecvSize); if (id == -1) { connection.Dispose(); break; } connection.channelID = id; _sendUdpControlTimeout = UDP_CONTROL_RESEND_TIMEOUT; SendUdpControl(connection); } else if (connection.pendingBytes[0] == (byte)EControlCode.AckChannelID) { connection.didHandshake = true; callbacks.OnConnect(connection); } else { // invalid response connection.Dispose(); break; } } else { connection.Dispose(); break; } connection.pendingRecvSize = 0; connection.pendingBytesReceived = 0; continue; } Array.Copy(connection.pendingBytes, buffer, connection.pendingRecvSize); var r = connection.pendingRecvSize; connection.pendingBytesReceived = 0; connection.pendingRecvSize = 0; metrics.bytesRecv += r; ++metrics.numPacketsRecv; callbacks.OnMessageReceived(connection, buffer, r); continue; } // not enough data ready break; } } Perf.End(); }
void SendTcpControlAck(SocketNetDriverConnection connection) { controlCodeBytes[0] = (byte)EControlCode.AckChannelID; connection.SendReliable(controlCodeBytes, 1); }