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
- HorizontalAlignConverter.cs
- WarningException.cs
- DataGridViewRowConverter.cs
- CalendarDataBindingHandler.cs
- CommentAction.cs
- TextEditorTables.cs
- ApplicationServiceHelper.cs
- TextTreeUndoUnit.cs
- SoapFault.cs
- SessionPageStateSection.cs
- SimpleBitVector32.cs
- QuerySafeNavigator.cs
- HttpInputStream.cs
- CompiledAction.cs
- MarginsConverter.cs
- TextSelectionProcessor.cs
- SiteMapNodeItemEventArgs.cs
- LineMetrics.cs
- Font.cs
- UserNameSecurityTokenProvider.cs
- BaseProcessor.cs
- DynamicPhysicalDiscoSearcher.cs
- sqlstateclientmanager.cs
- StructureChangedEventArgs.cs
- StrongName.cs
- ObjectViewListener.cs
- SafeArchiveContext.cs
- localization.cs
- AppSettings.cs
- WebEncodingValidator.cs
- DataControlCommands.cs
- BamlWriter.cs
- EventlogProvider.cs
- MultipartContentParser.cs
- EmptyControlCollection.cs
- TreeNodeCollectionEditor.cs
- WebPartDeleteVerb.cs
- DataGridViewCheckBoxCell.cs
- JoinSymbol.cs
- LineSegment.cs
- IssuedTokensHeader.cs
- XmlObjectSerializerWriteContext.cs
- ExtendedProperty.cs
- DataSet.cs
- DrawingAttributeSerializer.cs
- PeerResolverMode.cs
- PipeStream.cs
- WebServiceParameterData.cs
- TraceContextRecord.cs
- DebugView.cs
- SerializationInfoEnumerator.cs
- versioninfo.cs
- ProcessModelSection.cs
- EntityDataSourceContextDisposingEventArgs.cs
- WS2007HttpBindingElement.cs
- SerializationSectionGroup.cs
- SiteMapNodeCollection.cs
- TimeSpanOrInfiniteConverter.cs
- ExtendedPropertyCollection.cs
- LazyTextWriterCreator.cs
- listitem.cs
- DataSvcMapFileSerializer.cs
- PropertyIdentifier.cs
- WindowsToolbarAsMenu.cs
- IPEndPointCollection.cs
- SerializationStore.cs
- ExpandableObjectConverter.cs
- EntitySetRetriever.cs
- PersistChildrenAttribute.cs
- PixelFormat.cs
- ContentHostHelper.cs
- DataServiceContext.cs
- SqlDataSourceCache.cs
- SqlInfoMessageEvent.cs
- CharEntityEncoderFallback.cs
- SQLDecimal.cs
- TreeSet.cs
- AxHost.cs
- EditorResources.cs
- CellParagraph.cs
- ClientTargetSection.cs
- FileUtil.cs
- GroupDescription.cs
- CombinedGeometry.cs
- RuleProcessor.cs
- ClientSession.cs
- NotImplementedException.cs
- Console.cs
- EventLogTraceListener.cs
- CrossAppDomainChannel.cs
- ManagedCodeMarkers.cs
- DataDocumentXPathNavigator.cs
- TextServicesProperty.cs
- WebPartUtil.cs
- MatrixIndependentAnimationStorage.cs
- UserValidatedEventArgs.cs
- SerializationSectionGroup.cs
- TreeNode.cs
- RawStylusInputCustomDataList.cs
- GeneratedContractType.cs