SocketCache.cs

  1. // ==++==
  2. // 
  3. //   
  4. //    Copyright (c) 2002 Microsoft Corporation.  All rights reserved.
  5. //   
  6. //    The use and distribution terms for this software are contained in the file
  7. //    named license.txt, which can be found in the root of this distribution.
  8. //    By using this software in any fashion, you are agreeing to be bound by the
  9. //    terms of this license.
  10. //   
  11. //    You must not remove this notice, or any other, from this software.
  12. //   
  13. // 
  14. // ==--==
  15. //==========================================================================
  16. //  File:       SocketCache.cs
  17. //
  18. //  Summary:    Cache for client sockets.
  19. //
  20. //==========================================================================
  21. using System;
  22. using System.Collections;
  23. using System.Net;
  24. using System.Net.Sockets;
  25. using System.Runtime.Remoting;
  26. using System.Runtime.Remoting.Channels;
  27. using System.Threading;
  28. namespace System.Runtime.Remoting.Channels
  29. {
  30.     // Delegate to method that will fabricate the appropriate socket handler
  31.     internal delegate SocketHandler SocketHandlerFactory(Socket socket, 
  32.                                                          SocketCache socketCache,
  33.                                                          String machineAndPort);
  34.     // Used to cache client connections to a single port on a server
  35.     internal class RemoteConnection
  36.     {
  37.         private static char[] colonSep = new char[]{':'};
  38.     
  39.         private CachedSocketList _cachedSocketList;        
  40.         // reference back to the socket cache
  41.         private SocketCache _socketCache;        
  42.         // remote endpoint data
  43.         private String     _machineAndPort;
  44.         private IPEndPoint _ipEndPoint;
  45.         // socket timeout data        
  46.         private TimeSpan _socketLifetime = TimeSpan.FromSeconds(10);
  47.         
  48.         internal RemoteConnection(SocketCache socketCache, String machineAndPort)
  49.         {
  50.             _socketCache = socketCache;
  51.             _cachedSocketList = new CachedSocketList();
  52.             // parse "machinename:port"
  53.             String[] parts = machineAndPort.Split(colonSep);
  54.             String machineName = parts[0];
  55.             int port = Convert.ToInt32(parts[1]);
  56.         
  57.             _machineAndPort = machineAndPort;
  58.             IPAddress addr = null;
  59.             // we'll just let the exception bubble up if the machineName cannot
  60.             //   be resolved.
  61.             IPHostEntry ipEntries = Dns.Resolve(machineName);
  62.             if ((ipEntries != null) && (ipEntries.AddressList.Length > 0))
  63.             {
  64.                addr = ipEntries.AddressList[0];
  65.             }               
  66.             _ipEndPoint = new IPEndPoint(addr, port);
  67.         } // RemoteConnection
  68.         internal SocketHandler GetSocket()
  69.         {
  70.             // try the cached socket list
  71.             SocketHandler socketHandler = _cachedSocketList.GetSocket();
  72.             if (socketHandler != null)
  73.                 return socketHandler;
  74.             // Otherwise, we'll just create a new one.
  75.             return CreateNewSocket();
  76.         } // GetSocket
  77.         internal void ReleaseSocket(SocketHandler socket)
  78.         {
  79.             socket.ReleaseControl();
  80.             _cachedSocketList.ReturnSocket(socket);
  81.         } // ReleaseSocket
  82.         
  83.         private SocketHandler CreateNewSocket()
  84.         {        
  85.             Socket socket = new Socket(AddressFamily.InterNetwork,
  86.                                        SocketType.Stream,
  87.                                        ProtocolType.Tcp);
  88.             // disable nagle delays                                           
  89.             socket.SetSocketOption(SocketOptionLevel.Tcp, 
  90.                                    SocketOptionName.NoDelay,
  91.                                    1);
  92.             InternalRemotingServices.RemotingTrace("RemoteConnection::CreateNewSocket: connecting new socket :: " + _ipEndPoint);
  93.             socket.Connect(_ipEndPoint);
  94.             return _socketCache.CreateSocketHandler(socket, _machineAndPort);
  95.         } // CreateNewSocket
  96.         internal void TimeoutSockets(DateTime currentTime)
  97.         {            
  98.             _cachedSocketList.TimeoutSockets(currentTime, _socketLifetime);                 
  99.         } // TimeoutSockets
  100.             
  101.     } // class RemoteConnection
  102.     internal class CachedSocket
  103.     {
  104.         private SocketHandler _socket;
  105.         private DateTime      _socketLastUsed;
  106.         private CachedSocket _next;
  107.         internal CachedSocket(SocketHandler socket, CachedSocket next)
  108.         {
  109.             _socket = socket;
  110.             _socketLastUsed = DateTime.Now;
  111.             _next = next;
  112.         } // CachedSocket        
  113.         internal SocketHandler Handler { get { return _socket; } }
  114.         internal DateTime LastUsed { get { return _socketLastUsed; } }
  115.         internal CachedSocket Next 
  116.         {
  117.             get { return _next; }
  118.             set { _next = value; }
  119.         } 
  120.         
  121.     } // class CachedSocket
  122.     internal class CachedSocketList
  123.     {
  124.         private int _socketCount;
  125.         private CachedSocket _socketList; // linked list
  126.         internal CachedSocketList()
  127.         {
  128.             _socketCount = 0;
  129.             
  130.             _socketList = null;
  131.         } // CachedSocketList
  132.         
  133.         internal SocketHandler GetSocket()
  134.         {
  135.             if (_socketCount == 0)
  136.                 return null;
  137.         
  138.             lock (this)
  139.             {    
  140.                 if (_socketList != null)
  141.                 {
  142.                     SocketHandler socket = _socketList.Handler;
  143.                     _socketList = _socketList.Next;
  144.                     bool bRes = socket.RaceForControl();
  145.                     // We should always have control since there shouldn't
  146.                     //   be contention here.
  147.                     InternalRemotingServices.RemotingAssert(bRes, "someone else has the socket?");
  148.                     _socketCount--;
  149.                     return socket;
  150.                 }                                      
  151.             }
  152.             return null;
  153.         } // GetSocket
  154.         internal void ReturnSocket(SocketHandler socket)
  155.         {                        
  156.             lock (this)
  157.             {
  158.                 _socketList = new CachedSocket(socket, _socketList);
  159.                 _socketCount++;                      
  160.             }
  161.         } // ReturnSocket
  162.         internal void TimeoutSockets(DateTime currentTime, TimeSpan socketLifetime)
  163.         {            
  164.            lock (this)
  165.            {        
  166.                 CachedSocket prev = null;
  167.                 CachedSocket curr = _socketList;
  168.                 while (curr != null)
  169.                 {
  170.                     // see if it's lifetime has expired
  171.                     if ((currentTime - curr.LastUsed) > socketLifetime)
  172.                     {                        
  173.                         curr.Handler.Close();
  174.                         // remove current cached socket from list
  175.                         if (prev == null)
  176.                         {
  177.                             // it's the first item, so update _socketList
  178.                             _socketList = curr.Next;
  179.                             curr = _socketList;
  180.                         }
  181.                         else
  182.                         {
  183.                             // remove current item from the list
  184.                             curr = curr.Next;
  185.                             prev.Next = curr;
  186.                         }
  187.                         // decrement socket count
  188.                         _socketCount--;
  189.                     }       
  190.                     else
  191.                     {
  192.                         prev = curr;
  193.                         curr = curr.Next;
  194.                     }
  195.                 }          
  196.             }
  197.         } // TimeoutSockets
  198.         
  199.     } // class CachedSocketList
  200.     
  201.     internal class SocketCache
  202.     {
  203.         // collection of RemoteConnection's.
  204.         private Hashtable _connections = new Hashtable();
  205.         private SocketHandlerFactory _handlerFactory;
  206.         // socket timeout data
  207.         private RegisteredWaitHandle _registeredWaitHandle;
  208.         private WaitOrTimerCallback _socketTimeoutDelegate;
  209.         private AutoResetEvent _socketTimeoutWaitHandle;
  210.         private TimeSpan _socketTimeoutPollTime = TimeSpan.FromSeconds(10);
  211.         
  212.         internal SocketCache(SocketHandlerFactory handlerFactory)
  213.         {        
  214.             _handlerFactory = handlerFactory;
  215.             InitializeSocketTimeoutHandler();
  216.         } // SocketCache
  217.         private void InitializeSocketTimeoutHandler()
  218.         {
  219.             _socketTimeoutDelegate = new WaitOrTimerCallback(this.TimeoutSockets);
  220.             _socketTimeoutWaitHandle = new AutoResetEvent(false);
  221.             _registeredWaitHandle = 
  222.                 ThreadPool.UnsafeRegisterWaitForSingleObject(
  223.                     _socketTimeoutWaitHandle, 
  224.                     _socketTimeoutDelegate, 
  225.                     "TcpChannelSocketTimeout"
  226.                     _socketTimeoutPollTime, 
  227.                     true); // execute only once
  228.         } // InitializeSocketTimeoutHandler
  229.         private void TimeoutSockets(Object state, Boolean wasSignalled)
  230.         {
  231.             DateTime currentTime = DateTime.Now;
  232.             lock (_connections)
  233.             {
  234.                 foreach (DictionaryEntry entry in _connections)
  235.                 {
  236.                     RemoteConnection connection = (RemoteConnection)entry.Value; 
  237.                     connection.TimeoutSockets(currentTime);
  238.                 }
  239.             }
  240.             
  241.             _registeredWaitHandle.Unregister(null);
  242.             _registeredWaitHandle =
  243.                 ThreadPool.UnsafeRegisterWaitForSingleObject(
  244.                     _socketTimeoutWaitHandle, 
  245.                     _socketTimeoutDelegate, 
  246.                     "TcpChannelSocketTimeout"
  247.                     _socketTimeoutPollTime, 
  248.                     true); // execute only once      
  249.         } // TimeoutSockets
  250.         
  251.         internal SocketHandler CreateSocketHandler(Socket socket, String machineAndPort)
  252.         {
  253.             return _handlerFactory(socket, this, machineAndPort);
  254.         }
  255.         // The key is expected to of the form "machinename:port"
  256.         public SocketHandler GetSocket(String machineAndPort)
  257.         {
  258.             RemoteConnection connection = (RemoteConnection)_connections[machineAndPort];
  259.             if (connection == null)
  260.             {
  261.                 connection = new RemoteConnection(this, machineAndPort);
  262.                 // doesn't matter if different RemoteConnection's get written at
  263.                 //   the same time (GC will come along and close them).
  264.                 lock (_connections)
  265.                 {
  266.                     _connections[machineAndPort] = connection;
  267.                 }
  268.             }
  269.             return connection.GetSocket();
  270.         } // GetSocket
  271.         public void ReleaseSocket(String machineAndPort, SocketHandler socket)
  272.         {
  273.             RemoteConnection connection = (RemoteConnection)_connections[machineAndPort];
  274.             if (connection != null)
  275.             {
  276.                 connection.ReleaseSocket(socket);
  277.             }
  278.             else
  279.             {
  280.                 // there should have been a connection, so let's just close
  281.                 //   this socket.
  282.                 socket.Close();
  283.             }
  284.         } // ReleaseSocket
  285.         
  286.     } // SocketCache
  287. // namespace System.Runtime.Remoting.Channels
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值