/// <summary> /// Send a message through the TCP channel, and expect it to /// return unchanged /// </summary> /// <remarks> /// Useful for testing I/O levels 1 and 2. /// This method must be called between Setup() and TearDown(). /// </remarks> public static void DoMsgRoundTrip(string msg_send, string msg_expect) { byte[] to_send = System.Text.Encoding.ASCII.GetBytes(msg_send); using (var hs = new HttpSocket( new EchoSocket(bUseIPv6, to_send).socket)) { var msg_receive = hs.ReadAsciiLine(); Assert.AreEqual(msg_expect, msg_receive); hs.CloseSocket(); } }
/// <summary> /// Remove the socket contained in the given state object /// from the connected array list and hash table, then close the /// socket /// </summary> virtual protected void CloseSocket(HttpSocket state) { HttpSocket actual_state; lock (ConnectedSockets) { if (!ConnectedSockets.TryGetValue(state.id, out actual_state)) return; System.Diagnostics.Debug.Assert(actual_state == state); ConnectedSockets.Remove(state.id); } state.CloseSocket(); }
/// <summary> /// Close broken sockets /// </summary> /// <remarks> /// This function is called regularly to clean up the list of /// connected sockets. /// </remarks> void CheckSockets(object eventState) { Console.WriteLine("Starting Clean Sockets: {0}", ConnectedSockets.Count); try { lock (ConnectedSockets) { var toRemove = new List <int>(); foreach (var kv in ConnectedSockets) { try { int id = kv.Key; HttpSocket state = kv.Value; if (DateTime.Now - state.CreationTime > TimeSpan.FromMinutes(10)) { //Console.WriteLine("Closing Old Socket: {0} {1}", id, state.CreationTime); state.CloseSocket(); } if (state == null || state.IsSocketDead()) { toRemove.Add(id); } } catch (Exception e) { log.Error(e); } } foreach (var id in toRemove) { ConnectedSockets.Remove(id); } } } catch { } Console.WriteLine("Finished Clean Sockets: {0}", ConnectedSockets.Count); }
/// <summary> /// If necessary, connect the remote <c>SocketPS</c> socket /// to the given host and port /// </summary> /// <param name="hostname">Remote host name</param> /// <param name="port">Remote port</param> /// <remarks> /// If SocketPS is already connected to the right host and port, /// the socket is reused as is. /// </remarks> protected void Connect(string hostname, int port, bool secure) { System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(hostname)); System.Diagnostics.Debug.Assert(port > 0); if (DestinationHostName != null && DestinationHostName.Equals(hostname) && DestinationPort == port && (SocketPS != null && !SocketPS.IsSocketDead())) { // Nothing to do, just reuse the socket return; } if (SocketPS != null) { log.Debug("Changing hostname/port from " + DestinationHostName + ":" + DestinationPort + " to " + hostname + ":" + port); // We have a socket connected to the wrong host (or port) SocketPS.CloseSocket(); SocketPS = null; } IPAddress[] ips = Resolve(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; } log.Error(ee); } } if (socket == null) { throw e; } // Checked up, and good to go SocketPS = new HttpSocket(socket); if (secure) { SocketPS.MakeSecureClient(hostname); } DestinationHostName = hostname; DestinationPort = port; log.Debug("SocketPS connected to " + hostname + ":" + port); }
/// <summary> /// Remove the socket contained in the given state object /// from the connected array list and hash table, then close the /// socket /// </summary> protected virtual void CloseSocket(HttpSocket state) { HttpSocket actual_state; lock (ConnectedSockets) { if (!ConnectedSockets.TryGetValue(state.id, out actual_state)) return; System.Diagnostics.Debug.Assert(actual_state == state); ConnectedSockets.Remove(state.id); } state.CloseSocket(); }