Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / ManagedLibraries / Remoting / Channels / CORE / SocketCache.cs / 1305376 / SocketCache.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //========================================================================== // File: SocketCache.cs // // Summary: Cache for client sockets. // //========================================================================= using System; using System.Collections; using System.Net; using System.Net.Sockets; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Threading; namespace System.Runtime.Remoting.Channels { // Delegate to method that will fabricate the appropriate socket handler internal delegate SocketHandler SocketHandlerFactory(Socket socket, SocketCache socketCache, String machineAndPort); // Used to cache client connections to a single port on a server internal class RemoteConnection { private static char[] colonSep = new char[]{':'}; private CachedSocketList _cachedSocketList; // reference back to the socket cache private SocketCache _socketCache; // remote endpoint data private String _machineAndPort; private IPAddress[] _addressList; private int _port; private EndPoint _lkgIPEndPoint; private bool connectIPv6 = false; private Uri _uri; internal RemoteConnection(SocketCache socketCache, String machineAndPort) { _socketCache = socketCache; _cachedSocketList = new CachedSocketList(socketCache.SocketTimeout, socketCache.CachePolicy); // parse "machinename:port", add a dummy scheme to get uri parsing _uri = new Uri("dummy://" + machineAndPort); _port = _uri.Port; _machineAndPort = machineAndPort; } // RemoteConnection internal SocketHandler GetSocket() { // try the cached socket list SocketHandler socketHandler = _cachedSocketList.GetSocket(); if (socketHandler != null) return socketHandler; // Otherwise, we'll just create a new one. return CreateNewSocket(); } // GetSocket internal void ReleaseSocket(SocketHandler socket) { socket.ReleaseControl(); _cachedSocketList.ReturnSocket(socket); } // ReleaseSocket private bool HasIPv6Address(IPAddress[] addressList) { foreach (IPAddress address in addressList) { if (address.AddressFamily == AddressFamily.InterNetworkV6) return true; } return false; } private void DisableNagleDelays(Socket socket) { // disable nagle delays socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, 1); } private SocketHandler CreateNewSocket() { // // We should not cache the DNS result // _addressList = Dns.GetHostAddresses(_uri.Host); connectIPv6 = Socket.OSSupportsIPv6 && HasIPv6Address(_addressList); // If there is only one entry in the list, just use that // we will fail if the connect on it fails if (_addressList.Length == 1) return CreateNewSocket(new IPEndPoint(_addressList[0], _port)); // If LKG is set try using that if (_lkgIPEndPoint != null) { try{ return CreateNewSocket(_lkgIPEndPoint); } catch (Exception) { // Since this fail null out LKG _lkgIPEndPoint = null; } } // If IPv6 is enabled try connecting to IP addresses if (connectIPv6) { try{ return CreateNewSocket(AddressFamily.InterNetworkV6); }catch (Exception) {} } // If everything fails try ipv4 addresses return CreateNewSocket(AddressFamily.InterNetwork); } private SocketHandler CreateNewSocket(EndPoint ipEndPoint) { Socket socket = new Socket(ipEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); DisableNagleDelays(socket); InternalRemotingServices.RemotingTrace("RemoteConnection::CreateNewSocket: connecting new socket :: " + ipEndPoint); socket.Connect(ipEndPoint); _lkgIPEndPoint = socket.RemoteEndPoint; return _socketCache.CreateSocketHandler(socket, _machineAndPort); } // CreateNewSocket private SocketHandler CreateNewSocket(AddressFamily family) { Socket socket = new Socket(family, SocketType.Stream, ProtocolType.Tcp); DisableNagleDelays(socket); socket.Connect(_addressList, _port); _lkgIPEndPoint = socket.RemoteEndPoint; return _socketCache.CreateSocketHandler(socket, _machineAndPort); } // CreateNewSocket internal void TimeoutSockets(DateTime currentTime) { _cachedSocketList.TimeoutSockets(currentTime, _socketCache.SocketTimeout); } // TimeoutSockets } // class RemoteConnection internal class CachedSocket { private SocketHandler _socket; private DateTime _socketLastUsed; private CachedSocket _next; internal CachedSocket(SocketHandler socket, CachedSocket next) { _socket = socket; _socketLastUsed = DateTime.UtcNow; _next = next; } // CachedSocket internal SocketHandler Handler { get { return _socket; } } internal DateTime LastUsed { get { return _socketLastUsed; } } internal CachedSocket Next { get { return _next; } set { _next = value; } } } // class CachedSocket internal class CachedSocketList { private int _socketCount; private TimeSpan _socketLifetime; private SocketCachePolicy _socketCachePolicy; private CachedSocket _socketList; // linked list internal CachedSocketList(TimeSpan socketLifetime, SocketCachePolicy socketCachePolicy) { _socketCount = 0; _socketLifetime = socketLifetime; _socketCachePolicy = socketCachePolicy; _socketList = null; } // CachedSocketList internal SocketHandler GetSocket() { if (_socketCount == 0) return null; lock (this) { if (_socketList != null) { SocketHandler socket = _socketList.Handler; _socketList = _socketList.Next; bool bRes = socket.----ForControl(); // We should always have control since there shouldn't // be contention here. InternalRemotingServices.RemotingAssert(bRes, "someone else has the socket?"); _socketCount--; return socket; } } return null; } // GetSocket internal void ReturnSocket(SocketHandler socket) { TimeSpan socketActiveTime = DateTime.UtcNow - socket.CreationTime; bool closeSocket = false; lock (this) { // Check if socket active time has exceeded the lifetime // If it has just close the Socket if (_socketCachePolicy != SocketCachePolicy.AbsoluteTimeout || socketActiveTime < _socketLifetime) { // Ignore duplicate entries for the same socket handler for (CachedSocket curr = _socketList; curr != null; curr = curr.Next){ if (socket == curr.Handler) return; } _socketList = new CachedSocket(socket, _socketList); _socketCount++; } else { closeSocket = true; } } if(closeSocket) { socket.Close(); } } // ReturnSocket internal void TimeoutSockets(DateTime currentTime, TimeSpan socketLifetime) { lock (this) { CachedSocket prev = null; CachedSocket curr = _socketList; while (curr != null) { // see if it's lifetime has expired if ((_socketCachePolicy == SocketCachePolicy.AbsoluteTimeout && // This is for absolute (currentTime - curr.Handler.CreationTime) > socketLifetime) || (currentTime - curr.LastUsed) > socketLifetime) // This is relative behaviour { curr.Handler.Close(); // remove current cached socket from list if (prev == null) { // it's the first item, so update _socketList _socketList = curr.Next; curr = _socketList; } else { // remove current item from the list curr = curr.Next; prev.Next = curr; } // decrement socket count _socketCount--; } else { prev = curr; curr = curr.Next; } } } } // TimeoutSockets } // class CachedSocketList internal class SocketCache { // collection of RemoteConnection's. private static Hashtable _connections = new Hashtable(); private SocketHandlerFactory _handlerFactory; // socket timeout data private static RegisteredWaitHandle _registeredWaitHandle; private static WaitOrTimerCallback _socketTimeoutDelegate; private static AutoResetEvent _socketTimeoutWaitHandle; private static TimeSpan _socketTimeoutPollTime = TimeSpan.FromSeconds(10); private SocketCachePolicy _socketCachePolicy; private TimeSpan _socketTimeout; private int _receiveTimeout = 0; static SocketCache() { InitializeSocketTimeoutHandler(); } internal SocketCache(SocketHandlerFactory handlerFactory, SocketCachePolicy socketCachePolicy, TimeSpan socketTimeout) { _handlerFactory = handlerFactory; _socketCachePolicy = socketCachePolicy; _socketTimeout = socketTimeout; } // SocketCache internal TimeSpan SocketTimeout { get { return _socketTimeout; } set { _socketTimeout = value;} } internal int ReceiveTimeout { get { return _receiveTimeout; } set { _receiveTimeout = value;} } internal SocketCachePolicy CachePolicy { get { return _socketCachePolicy; } set { _socketCachePolicy = value;}} private static void InitializeSocketTimeoutHandler() { _socketTimeoutDelegate = new WaitOrTimerCallback(TimeoutSockets); _socketTimeoutWaitHandle = new AutoResetEvent(false); _registeredWaitHandle = ThreadPool.UnsafeRegisterWaitForSingleObject( _socketTimeoutWaitHandle, _socketTimeoutDelegate, "TcpChannelSocketTimeout", _socketTimeoutPollTime, true); // execute only once } // InitializeSocketTimeoutHandler private static void TimeoutSockets(Object state, Boolean wasSignalled) { DateTime currentTime = DateTime.UtcNow; lock (_connections) { foreach (DictionaryEntry entry in _connections) { RemoteConnection connection = (RemoteConnection)entry.Value; connection.TimeoutSockets(currentTime); } } _registeredWaitHandle.Unregister(null); _registeredWaitHandle = ThreadPool.UnsafeRegisterWaitForSingleObject( _socketTimeoutWaitHandle, _socketTimeoutDelegate, "TcpChannelSocketTimeout", _socketTimeoutPollTime, true); // execute only once } // TimeoutSockets internal SocketHandler CreateSocketHandler(Socket socket, String machineAndPort) { socket.ReceiveTimeout = _receiveTimeout; return _handlerFactory(socket, this, machineAndPort); } // The key is expected to of the form "machinename:port" public SocketHandler GetSocket(String machinePortAndSid, bool openNew) { RemoteConnection connection = (RemoteConnection)_connections[machinePortAndSid]; if (openNew || connection == null) { connection = new RemoteConnection(this, machinePortAndSid); // doesn't matter if different RemoteConnection's get written at // the same time (GC will come along and close them). lock (_connections) { _connections[machinePortAndSid] = connection; } } return connection.GetSocket(); } // GetSocket public void ReleaseSocket(String machinePortAndSid, SocketHandler socket) { RemoteConnection connection = (RemoteConnection)_connections[machinePortAndSid]; if (connection != null) { connection.ReleaseSocket(socket); } else { // there should have been a connection, so let's just close // this socket. socket.Close(); } } // ReleaseSocket } // SocketCache } // namespace System.Runtime.Remoting.Channels // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- QuaternionValueSerializer.cs
- PresentationSource.cs
- ValidationError.cs
- NativeMethods.cs
- DataMemberConverter.cs
- CompareValidator.cs
- DataGridTableCollection.cs
- DependencyObjectProvider.cs
- LinearKeyFrames.cs
- DataGridCell.cs
- XmlSchemaSimpleTypeList.cs
- QueryStringParameter.cs
- MembershipPasswordException.cs
- XmlJsonWriter.cs
- ErrorItem.cs
- PopupEventArgs.cs
- PairComparer.cs
- COM2PropertyDescriptor.cs
- Line.cs
- ObjectAssociationEndMapping.cs
- XPathDocumentBuilder.cs
- Context.cs
- SafeTimerHandle.cs
- ToolStripLocationCancelEventArgs.cs
- TypeDescriptor.cs
- Graph.cs
- TreeNodeStyle.cs
- CqlBlock.cs
- X509ChainPolicy.cs
- GetImportedCardRequest.cs
- DataSet.cs
- RealProxy.cs
- DigitShape.cs
- RtfToXamlReader.cs
- CompositeScriptReference.cs
- CornerRadiusConverter.cs
- XmlSchemaSubstitutionGroup.cs
- InstallerTypeAttribute.cs
- HelpInfo.cs
- TrackBarRenderer.cs
- MaskedTextBox.cs
- RequiredFieldValidator.cs
- TypeUnloadedException.cs
- StrokeNodeEnumerator.cs
- InkCanvasSelection.cs
- MemberMaps.cs
- SafeNativeMethods.cs
- SqlNamer.cs
- Ref.cs
- DropTarget.cs
- ThousandthOfEmRealPoints.cs
- ObjectCacheSettings.cs
- Stroke2.cs
- XmlUtil.cs
- IndentTextWriter.cs
- TagPrefixCollection.cs
- DataSourceXmlSerializationAttribute.cs
- HTMLTagNameToTypeMapper.cs
- BaseComponentEditor.cs
- DownloadProgressEventArgs.cs
- TableCellCollection.cs
- DataGridToolTip.cs
- XslTransform.cs
- KnownBoxes.cs
- SequenceDesigner.xaml.cs
- TargetConverter.cs
- TriggerCollection.cs
- CombinedHttpChannel.cs
- AppSettingsExpressionBuilder.cs
- RegexBoyerMoore.cs
- PrintEvent.cs
- SystemResourceKey.cs
- FontDriver.cs
- ExpressionBuilder.cs
- VisualTreeUtils.cs
- SqlConnectionHelper.cs
- FontUnit.cs
- CommittableTransaction.cs
- XmlSchemaAttributeGroupRef.cs
- ColumnClickEvent.cs
- CodeTypeDelegate.cs
- SqlFunctionAttribute.cs
- TlsSspiNegotiation.cs
- ThumbAutomationPeer.cs
- WmlCalendarAdapter.cs
- EmptyEnumerator.cs
- AppendHelper.cs
- _DigestClient.cs
- XmlSchemaSubstitutionGroup.cs
- IncrementalHitTester.cs
- MetadataPropertyvalue.cs
- SmtpException.cs
- HtmlInputImage.cs
- DefaultMemberAttribute.cs
- CapacityStreamGeometryContext.cs
- FileDialog_Vista_Interop.cs
- ChannelReliableSession.cs
- DocumentPage.cs
- PrintDocument.cs
- PassportPrincipal.cs