/// <summary> /// If necessary, connect the remote <c>RemoteSocket</c> socket /// to the given host and port /// </summary> /// <param name="hostname">Remote host name</param> /// <param name="port">Remote port</param> /// <remarks> /// If RemoteSocket is already connected to the right host and port, /// the socket is reused as is. /// </remarks> protected void Connect(string hostname, int port) { Debug.Assert(!String.IsNullOrEmpty(hostname)); Debug.Assert(port > 0); if (DestinationHostName != null && DestinationHostName.Equals(hostname) && DestinationPort == port && (RemoteSocket != null && !RemoteSocket.IsSocketDead())) { // Nothing to do, just reuse the socket return; } if (RemoteSocket != null) { // We have a socket connected to the wrong host (or port) RemoteSocket.CloseSocket(); RemoteSocket = null; } IPAddress[] ips = Dns.GetHostAddresses(hostname); Socket socket = null; Exception e = null; foreach (var ip in ips) { try { socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp); socket.Connect(ip, port); break; } catch (Exception ee) { if (ip.Equals(IPAddress.IPv6Loopback)) { // Do not log that continue; } if (e == null) { e = ee; } if (socket != null) { socket.Close(); socket = null; } } } if (socket == null) { throw e; } // Checked up, and good to go RemoteSocket = new SocketState(socket); DestinationHostName = hostname; DestinationPort = port; }
/// <summary> /// Close broken sockets /// </summary> /// <remarks> /// This function is called regularly to clean up the list of /// connected sockets. /// </remarks> private void CheckSockets(object eventState) { try { lock (ConnectedSockets) { foreach (var kv in ConnectedSockets) { try { Guid id = kv.Key; SocketState state = kv.Value; if (state == null || state.IsSocketDead()) { ConnectedSockets.Remove(id); } } catch (Exception e) {} } } } catch {} }
/// <summary> /// Callback method for accepting new connections /// </summary> private void AcceptCallback(IAsyncResult ar) { if (listeningThread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId) { new Thread(() => AcceptCallback(ar)).Start(); return; } if (IsShuttingDown) { return; } // Get the socket that handles the client request var listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Signal the main thread to continue listenThreadSwitch.Set(); // Create the state object var state = new SocketState(handler); state.guid = Guid.NewGuid(); lock (ConnectedSockets) { ConnectedSockets[state.guid] = state; } QTransfer transfer = null; try { transfer = new QTransfer(state); transfer.OnReceiveRequest = OnReceiveRequest; transfer.OnReceiveResponse = OnReceiveResponse; } catch (Exception e) { Console.WriteLine(e.Message); } if (transfer == null) { CloseSocket(state); return; } // No need for asynchronous I/O from now on try { while (transfer.LogicLoop()) { if (IsShuttingDown || state.IsSocketDead()) { break; } } } catch (SocketException) { /* ignore */ } catch (IoBroken) { /* ignore */ } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("Closing socket on error"); } CloseSocket(state); }
/// <summary> /// Callback method for accepting new connections /// </summary> private void AcceptCallback(IAsyncResult ar) { if (listeningThread.ManagedThreadId == Thread.CurrentThread.ManagedThreadId) { new Thread(() => AcceptCallback(ar)).Start(); return; } if (IsShuttingDown) { return; } // Get the socket that handles the client request var listener = (Socket)ar.AsyncState; Socket handler = listener.EndAccept(ar); // Signal the main thread to continue listenThreadSwitch.Set(); // Create the state object var state = new SocketState(handler); state.guid = Guid.NewGuid(); lock (ConnectedSockets) { ConnectedSockets[state.guid] = state; } QTransfer transfer = null; try { transfer = new QTransfer(state); transfer.OnReceiveRequest = OnReceiveRequest; transfer.OnReceiveResponse = OnReceiveResponse; } catch (Exception e) { Console.WriteLine(e.Message); } if (transfer == null) { CloseSocket(state); return; } // No need for asynchronous I/O from now on try { while (transfer.LogicLoop()) { if (IsShuttingDown || state.IsSocketDead()) { break; } } } catch (SocketException) { /* ignore */ } catch (IoBroken) { /* ignore */ } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine("Closing socket on error"); } CloseSocket(state); }