/// <summary> /// 判断是否存在到服务器的连接 /// </summary> /// <returns></returns> public static bool ExistConnection() { //Use IPAddress.Any to match all IPAddresses. Use port number 0 to match all port numbers. IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 0); return(NetworkComms.ConnectionExists(new IPEndPoint(IPAddress.Parse(serverIp), serverPort), localEndPoint, ConnectionType.TCP)); }
/// <inheritdoc /> protected override void StartIncomingDataListen() { if (!NetworkComms.ConnectionExists(ConnectionInfo.RemoteEndPoint, ConnectionInfo.LocalEndPoint, ConnectionType.Bluetooth, ConnectionInfo.ApplicationLayerProtocol)) { CloseConnection(true, 18); throw new ConnectionSetupException("A connection reference by endPoint should exist before starting an incoming data listener."); } lock (SyncRoot) { if (NetworkComms.ConnectionListenModeUseSync) { if (incomingDataListenThread == null) { incomingDataListenThread = new Thread(IncomingBluetoothDataSyncWorker); //Incoming data always gets handled in a time critical fashion incomingDataListenThread.Priority = NetworkComms.timeCriticalThreadPriority; incomingDataListenThread.Name = "BT_IncomingDataListener"; incomingDataListenThread.IsBackground = true; incomingDataListenThread.Start(); } } else { btClientNetworkStream.BeginRead(dataBuffer, 0, dataBuffer.Length, new AsyncCallback(IncomingBluetoothPacketHandler), btClientNetworkStream); } } if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Listening for incoming data from " + ConnectionInfo); } }
/// <inheritdoc /> protected override void StartIncomingDataListen() { if (!NetworkComms.ConnectionExists(ConnectionInfo.RemoteIPEndPoint, ConnectionInfo.LocalIPEndPoint, ConnectionType.TCP, ConnectionInfo.ApplicationLayerProtocol)) { CloseConnection(true, 18); throw new ConnectionSetupException("A connection reference by endPoint should exist before starting an incoming data listener."); } #if WINDOWS_PHONE var stream = socket.InputStream.AsStreamForRead(); stream.BeginRead(dataBuffer, 0, dataBuffer.Length, new AsyncCallback(IncomingTCPPacketHandler), stream); #elif NETFX_CORE Task readTask = new Task(async() => { var buffer = Windows.Security.Cryptography.CryptographicBuffer.CreateFromByteArray(dataBuffer); var readBuffer = await socket.InputStream.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.Partial); await IncomingTCPPacketHandler(readBuffer); }); readTask.Start(); #else lock (SyncRoot) { if (NetworkComms.ConnectionListenModeUseSync) { if (incomingDataListenThread == null) { incomingDataListenThread = new Thread(IncomingTCPDataSyncWorker); //Incoming data always gets handled in a time critical fashion incomingDataListenThread.Priority = NetworkComms.timeCriticalThreadPriority; incomingDataListenThread.Name = "UDP_IncomingDataListener"; incomingDataListenThread.IsBackground = true; incomingDataListenThread.Start(); } } else { if (asyncListenStarted) { throw new ConnectionSetupException("Async listen already started. Why has this been called twice?."); } asyncListenerInRead = true; connectionStream.BeginRead(dataBuffer, 0, dataBuffer.Length, new AsyncCallback(IncomingTCPPacketHandler), connectionStream); asyncListenStarted = true; } } #endif if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Listening for incoming data from " + ConnectionInfo); } }
/// <summary> /// Create a new connection object /// </summary> /// <param name="connectionInfo">ConnecitonInfo corresponding to the new connection</param> /// <param name="defaultSendReceiveOptions">The SendReceiveOptions which should be used as connection defaults</param> protected Connection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions) { SendTimesMSPerKBCache = new CommsMath(); dataBuffer = new byte[NetworkComms.ReceiveBufferSizeBytes]; packetBuilder = new PacketBuilder(); //Intialise the sequence counter using the global value //Subsequent values on this connection are guaranteed to be sequential packetSequenceCounter = Interlocked.Increment(ref NetworkComms.totalPacketSendCount); ConnectionInfo = connectionInfo; if (defaultSendReceiveOptions != null) { ConnectionDefaultSendReceiveOptions = defaultSendReceiveOptions; } else { ConnectionDefaultSendReceiveOptions = NetworkComms.DefaultSendReceiveOptions; } if (NetworkComms.commsShutdown) { throw new ConnectionSetupException("Attempting to create new connection after global comms shutdown has been initiated."); } if (ConnectionInfo.ConnectionType == ConnectionType.Undefined || ConnectionInfo.RemoteEndPoint == null) { throw new ConnectionSetupException("ConnectionType and RemoteEndPoint must be defined within provided ConnectionInfo."); } //If a connection already exists with this info then we can throw an exception here to prevent duplicates if (NetworkComms.ConnectionExists(connectionInfo.RemoteEndPoint, connectionInfo.ConnectionType)) { throw new ConnectionSetupException("A connection already exists with " + ConnectionInfo); } //We add a reference in the constructor to ensure any duplicate connection problems are picked up here NetworkComms.AddConnectionByReferenceEndPoint(this); }
/// <summary> /// Starts listening for incoming data on this TCP connection /// </summary> protected override void StartIncomingDataListen() { if (!NetworkComms.ConnectionExists(ConnectionInfo.RemoteEndPoint, ConnectionType.TCP)) { CloseConnection(true, 18); throw new ConnectionSetupException("A connection reference by endPoint should exist before starting an incoming data listener."); } #if WINDOWS_PHONE var stream = socket.InputStream.AsStreamForRead(); stream.BeginRead(dataBuffer, 0, dataBuffer.Length, new AsyncCallback(IncomingTCPPacketHandler), stream); #else lock (delegateLocker) { if (NetworkComms.ConnectionListenModeUseSync) { if (incomingDataListenThread == null) { incomingDataListenThread = new Thread(IncomingTCPDataSyncWorker); //Incoming data always gets handled in a time critical fashion incomingDataListenThread.Priority = NetworkComms.timeCriticalThreadPriority; incomingDataListenThread.Name = "IncomingDataListener"; incomingDataListenThread.Start(); } } else { tcpClientNetworkStream.BeginRead(dataBuffer, 0, dataBuffer.Length, new AsyncCallback(IncomingTCPPacketHandler), tcpClientNetworkStream); } } #endif if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Listening for incoming data from " + ConnectionInfo); } }
/// <summary> /// Create a new connection object /// </summary> /// <param name="connectionInfo">ConnectionInfo corresponding to the new connection</param> /// <param name="defaultSendReceiveOptions">The SendReceiveOptions which should be used as connection defaults</param> protected Connection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions) { //If the application layer protocol is disabled the serialiser must be NullSerializer //and no data processors are allowed. if (connectionInfo.ApplicationLayerProtocol == ApplicationLayerProtocolStatus.Disabled) { if (defaultSendReceiveOptions.Options.ContainsKey("ReceiveConfirmationRequired")) { throw new ArgumentException("Attempted to create an unmanaged connection when the provided send receive" + " options specified the ReceiveConfirmationRequired option. Please provide compatible send receive options in order to successfully" + " instantiate this unmanaged connection.", "defaultSendReceiveOptions"); } if (defaultSendReceiveOptions.DataSerializer != DPSManager.GetDataSerializer <NullSerializer>()) { throw new ArgumentException("Attempted to create an unmanaged connection when the provided send receive" + " options serialiser was not NullSerializer. Please provide compatible send receive options in order to successfully" + " instantiate this unmanaged connection.", "defaultSendReceiveOptions"); } if (defaultSendReceiveOptions.DataProcessors.Count > 0) { throw new ArgumentException("Attempted to create an unmanaged connection when the provided send receive" + " options contains data processors. Data processors may not be used with unmanaged connections." + " Please provide compatible send receive options in order to successfully instantiate this unmanaged connection.", "defaultSendReceiveOptions"); } } SendTimesMSPerKBCache = new CommsMath(); packetBuilder = new PacketBuilder(); //Initialise the sequence counter using the global value //Subsequent values on this connection are guaranteed to be sequential packetSequenceCounter = Interlocked.Increment(ref NetworkComms.totalPacketSendCount); ConnectionInfo = connectionInfo; if (defaultSendReceiveOptions != null) { ConnectionDefaultSendReceiveOptions = defaultSendReceiveOptions; } else { ConnectionDefaultSendReceiveOptions = NetworkComms.DefaultSendReceiveOptions; } //Add any listener specific packet handlers if required if (connectionInfo.ConnectionListener != null) { connectionInfo.ConnectionListener.AddListenerPacketHandlersToConnection(this); } if (NetworkComms.commsShutdown) { throw new ConnectionSetupException("Attempting to create new connection after global NetworkComms.Net shutdown has been initiated."); } if (ConnectionInfo.ConnectionType == ConnectionType.Undefined || ConnectionInfo.RemoteEndPoint == null) { throw new ConnectionSetupException("ConnectionType and RemoteEndPoint must be defined within provided ConnectionInfo."); } //If a connection already exists with this info then we can throw an exception here to prevent duplicates if (NetworkComms.ConnectionExists(connectionInfo.RemoteEndPoint, connectionInfo.LocalEndPoint, connectionInfo.ConnectionType, connectionInfo.ApplicationLayerProtocol)) { throw new ConnectionSetupException("A " + connectionInfo.ConnectionType.ToString() + " connection already exists with info " + connectionInfo); } //We add a reference in the constructor to ensure any duplicate connection problems are picked up here NetworkComms.AddConnectionReferenceByRemoteEndPoint(this); }
/// <summary> /// Internal UDP creation method that performs the necessary tasks /// </summary> /// <param name="connectionInfo"></param> /// <param name="defaultSendReceiveOptions"></param> /// <param name="level"></param> /// <param name="listenForReturnPackets"></param> /// <param name="existingConnection"></param> /// <returns></returns> internal static UDPConnection GetConnection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions, UDPOptions level, bool listenForReturnPackets, UDPConnection existingConnection) { connectionInfo.ConnectionType = ConnectionType.UDP; UDPConnection connection = null; lock (NetworkComms.globalDictAndDelegateLocker) { if (NetworkComms.ConnectionExists(connectionInfo.RemoteEndPoint, ConnectionType.UDP)) { connection = (UDPConnection)NetworkComms.GetExistingConnection(connectionInfo.RemoteEndPoint, ConnectionType.UDP); } else { //If we are listening on what will be the outgoing adaptor we send with that client to ensure if our connection info is handed off we are connectable by others if (existingConnection == null) { try { IPEndPoint localEndPoint = NetworkComms.BestLocalEndPoint(connectionInfo.RemoteEndPoint); lock (udpClientListenerLocker) { IPEndPoint existingLocalEndPoint = ExistingLocalListenEndPoints(localEndPoint.Address); if (existingLocalEndPoint != null) { existingConnection = udpConnectionListeners[existingLocalEndPoint]; //If we are using an existing listener there is no need to listen for packets listenForReturnPackets = false; } } } catch (Exception) { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Failed to determine preferred existing udpClientListener to " + connectionInfo.RemoteEndPoint.Address + ":" + connectionInfo.RemoteEndPoint.Port.ToString() + ". Will create an isolated udp connection instead."); } } } //If an existing connection does not exist but the info we are using suggests it should we need to reset the info //so that it can be reused correctly. This case generally happens when using Comms in the format //UDPConnection.GetConnection(info).SendObject(packetType, objToSend); if (connectionInfo.ConnectionState == ConnectionState.Established || connectionInfo.ConnectionState == ConnectionState.Shutdown) { connectionInfo.ResetConnectionInfo(); } connection = new UDPConnection(connectionInfo, defaultSendReceiveOptions, level, listenForReturnPackets, existingConnection); } } if (!NetworkComms.commsShutdown) { TriggerConnectionKeepAliveThread(); } return(connection); }
internal static TCPConnection GetConnection(ConnectionInfo connectionInfo, SendReceiveOptions defaultSendReceiveOptions, TcpClient tcpClient, bool establishIfRequired = true) #endif { connectionInfo.ConnectionType = ConnectionType.TCP; //If we have a tcpClient at this stage we must be serverside #if WINDOWS_PHONE if (socket != null) { connectionInfo.ServerSide = true; } #else if (tcpClient != null) { connectionInfo.ServerSide = true; } #endif bool newConnection = false; TCPConnection connection; lock (NetworkComms.globalDictAndDelegateLocker) { //Check to see if a conneciton already exists, if it does return that connection, if not return a new one if (NetworkComms.ConnectionExists(connectionInfo.RemoteEndPoint, connectionInfo.ConnectionType)) { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Attempted to create new TCPConnection to connectionInfo='" + connectionInfo + "' but there is an existing connection. Existing connection will be returned instead."); } establishIfRequired = false; connection = (TCPConnection)NetworkComms.GetExistingConnection(connectionInfo.RemoteEndPoint, connectionInfo.ConnectionType); } else { if (NetworkComms.LoggingEnabled) { NetworkComms.Logger.Trace("Creating new TCPConnection to connectionInfo='" + connectionInfo + "'." + (establishIfRequired ? " Connection will be established." : " Connection will not be established.")); } if (connectionInfo.ConnectionState == ConnectionState.Establishing) { throw new ConnectionSetupException("Connection state for connection " + connectionInfo + " is marked as establishing. This should only be the case here due to a bug."); } //If an existing connection does not exist but the info we are using suggests it should we need to reset the info //so that it can be reused correctly. This case generally happens when using Comms in the format //TCPConnection.GetConnection(info).SendObject(packetType, objToSend); if (connectionInfo.ConnectionState == ConnectionState.Established || connectionInfo.ConnectionState == ConnectionState.Shutdown) { connectionInfo.ResetConnectionInfo(); } //We add a reference to networkComms for this connection within the constructor #if WINDOWS_PHONE connection = new TCPConnection(connectionInfo, defaultSendReceiveOptions, socket); #else connection = new TCPConnection(connectionInfo, defaultSendReceiveOptions, tcpClient); #endif newConnection = true; } } if (newConnection && establishIfRequired) { connection.EstablishConnection(); } else if (!newConnection) { connection.WaitForConnectionEstablish(NetworkComms.ConnectionEstablishTimeoutMS); } if (!NetworkComms.commsShutdown) { TriggerConnectionKeepAliveThread(); } return(connection); }