SocketManager.cs

本文介绍了一个用于管理Socket连接的抽象类SocketHandler,该类提供了一系列的方法来处理网络数据的读写操作,包括异步读取、缓冲管理和错误处理等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
  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:       SocketManager.cs
  17. //
  18. //  Summary:    Class for managing a socket connection.
  19. //
  20. //==========================================================================
  21. using System;
  22. using System.IO;
  23. using System.Net;
  24. using System.Net.Sockets;
  25. using System.Runtime.Remoting.Messaging;
  26. using System.Text;
  27. using System.Threading;
  28. namespace System.Runtime.Remoting.Channels
  29. {
  30.     internal delegate bool ValidateByteDelegate(byte b);
  31.     internal abstract class SocketHandler
  32.     {
  33.         // socket manager data
  34.         protected Socket NetSocket;    // network socket
  35.         protected Stream NetStream; // network stream
  36.         private RequestQueue _requestQueue; // request queue to use for this connection
  37.         private byte[] _dataBuffer; // buffered data
  38.         private int    _dataBufferSize; // size of data buffer
  39.         private int    _dataOffset; // offset of remaining data in buffer
  40.         private int    _dataCount;  // count of remaining bytes in buffer
  41.         private AsyncCallback _beginReadCallback; // callback to use when doing an async read
  42.         private IAsyncResult _beginReadAsyncResult; // async result from doing a begin read
  43.         private WaitCallback _dataArrivedCallback; // callback to signal once data is available
  44.         private Object _dataArrivedCallbackState; // state object to go along with callback
  45.         
  46.         private byte[] _byteBuffer = new byte[4]; // buffer for reading bytes
  47.         // control cookie -
  48.         //   The control cookie is used for synchronization when a "user"
  49.         //   wants to retrieve this client socket manager from the socket
  50.         //   cache.
  51.         private int _controlCookie = 1;
  52.                     
  53.         // hide default constructor        
  54.         private SocketHandler(){}
  55.         public SocketHandler(Socket socket)
  56.         {        
  57.             _beginReadCallback = new AsyncCallback(this.BeginReadMessageCallback);
  58.         
  59.             NetSocket = socket;
  60.             NetStream = new SocketStream(NetSocket);
  61.             _dataBuffer = CoreChannel.BufferPool.GetBuffer();
  62.             _dataBufferSize = _dataBuffer.Length;
  63.             _dataOffset = 0;
  64.             _dataCount = 0;
  65.         } // SocketHandler
  66.         internal SocketHandler(Socket socket, RequestQueue requestQueue) : this(socket)
  67.         {        
  68.             _requestQueue = requestQueue;
  69.         } // SocketHandler
  70.         // If this method returns true, then whoever called it can assume control
  71.         //   of the client socket manager. If it returns false, the caller is on
  72.         //   their honor not to do anything further with this object.
  73.         public bool RaceForControl()
  74.         {
  75.             if (1 == Interlocked.Exchange(ref _controlCookie, 0))
  76.                 return true;
  77.             return false;            
  78.         } // RaceForControl
  79.         public void ReleaseControl()
  80.         {
  81.             _controlCookie = 1;
  82.         } // ReleaseControl
  83.         // Determines if the remote connection is from localhost.
  84.         internal bool IsLocal()
  85.         {
  86.             IPAddress remoteAddr = ((IPEndPoint)NetSocket.RemoteEndPoint).Address;
  87.             return remoteAddr.Address == IPAddress.Loopback.Address;
  88.         } // IsLocal
  89.         
  90.         // does any necessary cleanup before reading the incoming message
  91.         protected abstract void PrepareForNewMessage();
  92.         // allows derived classes to send an error message if the async read
  93.         //   in BeginReadMessage fails.
  94.         protected virtual void SendErrorMessageIfPossible(Exception e)
  95.         {
  96.         }     
  97.         // allows socket handler to do something when an input stream it handed
  98.         //   out is closed. The input stream is responsible for calling this method.
  99.         //   (usually, only client socket handlers will do anything with this).
  100.         //   (input stream refers to data being read off of the network)
  101.         public virtual void OnInputStreamClosed()
  102.         {            
  103.         }
  104.         
  105.         public virtual void Close()
  106.         {        
  107.             if (_requestQueue != null)
  108.                 _requestQueue.ScheduleMoreWorkIfNeeded();
  109.         
  110.             if (NetStream != null)
  111.             {
  112.                 NetStream.Close();
  113.                 NetStream = null;
  114.             }
  115.         
  116.             if (NetSocket != null)
  117.             {
  118.                 NetSocket.Close();
  119.                 NetSocket = null;
  120.             }
  121.             // return buffer to the pool
  122.             if (_dataBuffer != null)
  123.             {
  124.                 CoreChannel.BufferPool.ReturnBuffer(_dataBuffer);
  125.                 _dataBuffer = null;
  126.             }
  127.         } // Close
  128.         public WaitCallback DataArrivedCallback
  129.         {
  130.             get { return _dataArrivedCallback; }
  131.             set { _dataArrivedCallback = value; }            
  132.         } // DataArrivedCallback
  133.         public Object DataArrivedCallbackState
  134.         {
  135.             get { return _dataArrivedCallbackState; }
  136.             set { _dataArrivedCallbackState = value; }
  137.         } // DataArrivedCallbackState
  138.         
  139.         public void BeginReadMessage()
  140.         {        
  141.             bool bProcessNow = false;
  142.         
  143.             try
  144.             {
  145.                 if (_requestQueue != null)
  146.                     _requestQueue.ScheduleMoreWorkIfNeeded();
  147.         
  148.                 PrepareForNewMessage();       
  149.   
  150.                 if (_dataCount == 0)
  151.                 {
  152.                     _beginReadAsyncResult =
  153.                         NetStream.BeginRead(_dataBuffer, 0, _dataBufferSize, 
  154.                                             _beginReadCallback, null);
  155.                 }
  156.                 else
  157.                 {            
  158.                     // just queue the request if we already have some data
  159.                     //   (note: we intentionally don't call the callback directly to avoid
  160.                     //    overflowing the stack if we service a bunch of calls)    
  161.                     bProcessNow = true;
  162.                 }
  163.             }
  164.             catch (Exception e)
  165.             {
  166.                 CloseOnFatalError(e);
  167.             }
  168.             if (bProcessNow)
  169.             {
  170.                 if (_requestQueue != null)
  171.                     _requestQueue.ProcessNextRequest(this);
  172.                 else
  173.                     ProcessRequestNow();
  174.      
  175.                 _beginReadAsyncResult = null;
  176.             }
  177.         } // BeginReadMessage
  178.         public void BeginReadMessageCallback(IAsyncResult ar)
  179.         {        
  180.             bool bProcessRequest = false;
  181.         
  182.             // data has been buffered; proceed to call provided callback
  183.             try
  184.             {
  185.                 _beginReadAsyncResult = null;  
  186.             
  187.                 _dataOffset = 0;              
  188.                 _dataCount = NetStream.EndRead(ar);
  189.                 if (_dataCount <= 0)
  190.                 {
  191.                     // socket has been closed
  192.                     Close();
  193.                 }
  194.                 else
  195.                 {
  196.                     bProcessRequest = true;
  197.                 }
  198.             }
  199.             catch (Exception e)
  200.             {        
  201.                 CloseOnFatalError(e);       
  202.             }
  203.             if (bProcessRequest)
  204.             {
  205.                 if (_requestQueue != null)
  206.                     _requestQueue.ProcessNextRequest(this);
  207.                 else
  208.                     ProcessRequestNow();
  209.             }
  210.         } // BeginReadMessageCallback     
  211.         internal void CloseOnFatalError(Exception e)
  212.         {
  213.             try
  214.             {
  215.                SendErrorMessageIfPossible(e);
  216.               
  217.                // Something bad happened, so we should just close everything and 
  218.                // return any buffers to the pool.
  219.                Close();
  220.             }
  221.             catch
  222.             {
  223.                 try
  224.                 {
  225.                     Close();
  226.                 }
  227.                 catch
  228.                 {
  229.                     // this is to prevent any weird errors with closing
  230.                     // a socket from showing up as an unhandled exception.
  231.                 }
  232.             }
  233.         } // CloseOnFatalError
  234.         // Called when the SocketHandler is pulled off the pending request queue.
  235.         internal void ProcessRequestNow()
  236.         {
  237.             try
  238.             {
  239.                 WaitCallback waitCallback = _dataArrivedCallback;
  240.                 if (waitCallback != null)
  241.                     waitCallback.Invoke(this); 
  242.             }
  243.             catch (Exception e)
  244.             {          
  245.                 CloseOnFatalError(e);                
  246.             }            
  247.         } // ProcessRequestNow
  248.         internal void RejectRequestNowSinceServerIsBusy()
  249.         {       
  250.             CloseOnFatalError(
  251.                 new RemotingException(
  252.                         CoreChannel.GetResourceString("Remoting_ServerIsBusy")));                 
  253.         } // RejectRequestNow
  254.         public int ReadByte()
  255.         {
  256.             if (Read(_byteBuffer, 0, 1) != -1)
  257.                 return _byteBuffer[0];
  258.             else
  259.                 return -1;
  260.         } // ReadByte
  261.         public void WriteByte(byte value, Stream outputStream)
  262.         {
  263.             _byteBuffer[0] = value;
  264.             outputStream.Write(_byteBuffer, 0, 1);
  265.         } // WriteUInt16
  266.         public UInt16 ReadUInt16() 
  267.         {
  268.             Read(_byteBuffer, 0, 2);
  269.         
  270.             return (UInt16)(_byteBuffer[0] & 0xFF | _byteBuffer[1] << 8);
  271.         } // ReadUInt16
  272.         
  273.         public void WriteUInt16(UInt16 value, Stream outputStream)
  274.         {
  275.             _byteBuffer[0] = (byte)value;
  276.             _byteBuffer[1] = (byte)(value >> 8);
  277.             outputStream.Write(_byteBuffer, 0, 2);
  278.         } // WriteUInt16
  279.         public int ReadInt32() 
  280.         {
  281.             Read(_byteBuffer, 0, 4);
  282.         
  283.             return (int)((_byteBuffer[0] & 0xFF) |
  284.                           _byteBuffer[1] << 8 |
  285.                           _byteBuffer[2] << 16 |
  286.                           _byteBuffer[3] << 24);
  287.         } // ReadInt32
  288.         public void WriteInt32(int value, Stream outputStream)
  289.         {
  290.             _byteBuffer[0] = (byte)value;
  291.             _byteBuffer[1] = (byte)(value >> 8);
  292.             _byteBuffer[2] = (byte)(value >> 16);
  293.             _byteBuffer[3] = (byte)(value >> 24);
  294.             outputStream.Write(_byteBuffer, 0, 4);
  295.         } // WriteInt32
  296.         protected bool ReadAndMatchFourBytes(byte[] buffer)
  297.         {
  298.             InternalRemotingServices.RemotingAssert(buffer.Length == 4, "expecting 4 byte buffer.");
  299.             Read(_byteBuffer, 0, 4);
  300.             
  301.             bool bMatch = 
  302.                 (_byteBuffer[0] == buffer[0]) &
  303.                 (_byteBuffer[1] == buffer[1]) &
  304.                 (_byteBuffer[2] == buffer[2]) &
  305.                 (_byteBuffer[3] == buffer[3]);
  306.             return bMatch;
  307.         } // ReadAndMatchFourBytes
  308.         
  309.         public int Read(byte[] buffer, int offset, int count)
  310.         {
  311.             int totalBytesRead = 0;
  312.             // see if we have buffered data
  313.             if (_dataCount > 0)
  314.             {
  315.                 // copy minimum of buffered data size and bytes left to read
  316.                 int readCount = Math.Min(_dataCount, count);
  317.                 StreamHelper.BufferCopy(_dataBuffer, _dataOffset, buffer, offset, readCount);
  318.                 _dataCount -= readCount;
  319.                 _dataOffset += readCount;
  320.                 count -= readCount;
  321.                 offset += readCount;
  322.                 totalBytesRead += readCount;
  323.             }
  324.             // keep reading (whoever is calling this will make sure that they
  325.             //   don't try to read too much).
  326.             while (count > 0)
  327.             {                
  328.                 if (count < 256)
  329.                 {
  330.                     // if count is less than 256 bytes, I will buffer more data
  331.                     // because it's not worth making a socket request for less.
  332.                     BufferMoreData();
  333.                     // copy minimum of buffered data size and bytes left to read
  334.                     int readCount = Math.Min(_dataCount, count);
  335.                     StreamHelper.BufferCopy(_dataBuffer, _dataOffset, buffer, offset, readCount);
  336.                     _dataCount -= readCount;
  337.                     _dataOffset += readCount;
  338.                     count -= readCount;
  339.                     offset += readCount;
  340.                     totalBytesRead += readCount;    
  341.                 }
  342.                 else
  343.                 {
  344.                     // just go directly to the socket
  345.                     
  346.                     // the internal buffer is guaranteed to be empty at this point, so just
  347.                     //   read directly into the array given
  348.                 
  349.                     int readCount = ReadFromSocket(buffer, offset, count);                    
  350.                     count -= readCount;
  351.                     offset += readCount;
  352.                     totalBytesRead += readCount;
  353.                 }
  354.             }
  355.                         
  356.             return totalBytesRead;
  357.         } // Read
  358.         // This should only be called when _dataCount is 0.
  359.         private int BufferMoreData()
  360.         {        
  361.             InternalRemotingServices.RemotingAssert(_dataCount == 0, 
  362.                 "SocketHandler::BufferMoreData called with data still in buffer." +
  363.                 "DataCount=" + _dataCount + "; DataOffset" + _dataOffset);
  364.             int bytesRead = ReadFromSocket(_dataBuffer, 0, _dataBufferSize);
  365.                 
  366.             _dataOffset = 0;
  367.             _dataCount = bytesRead;
  368.             return bytesRead;
  369.         } // BufferMoreData
  370.         private int ReadFromSocket(byte[] buffer, int offset, int count)
  371.         {
  372.             int bytesRead = NetStream.Read(buffer, offset, count);
  373.             if (bytesRead <= 0)
  374.             {
  375.                 throw new RemotingException(       
  376.                     CoreChannel.GetResourceString("Remoting_Socket_UnderlyingSocketClosed"));
  377.             }
  378.             return bytesRead;
  379.         } // ReadFromSocket
  380.         
  381.         protected byte[] ReadToByte(byte b)
  382.         {
  383.             return ReadToByte(b, null);
  384.         } /// ReadToByte
  385.         protected byte[] ReadToByte(byte b, ValidateByteDelegate validator)
  386.         {
  387.             byte[] readBytes = null;
  388.             // start at current position and return byte array consisting of bytes
  389.             //   up to where we found the byte.
  390.             if (_dataCount == 0)
  391.                 BufferMoreData();
  392.                 
  393.             int dataEnd = _dataOffset + _dataCount; // one byte past last valid byte
  394.             int startIndex = _dataOffset; // current position
  395.             int endIndex = startIndex; // current index
  396.             bool foundByte = false;
  397.             bool bufferEnd;
  398.             while (!foundByte)
  399.             {            
  400.                 InternalRemotingServices.RemotingAssert(endIndex <= dataEnd, "endIndex shouldn't pass dataEnd");
  401.                 bufferEnd = endIndex == dataEnd;
  402.                 foundByte = !bufferEnd && (_dataBuffer[endIndex] == b);
  403.                 // validate character if necessary
  404.                 if ((validator != null) && !bufferEnd && !foundByte)
  405.                 {
  406.                     if (!validator(_dataBuffer[endIndex]))
  407.                     {
  408.                         throw new RemotingException(
  409.                             CoreChannel.GetResourceString(
  410.                                 "Remoting_Http_InvalidDataReceived"));
  411.                     }
  412.                 }
  413.                 // we're at the end of the currently buffered data or we've found our byte
  414.                 if (bufferEnd || foundByte)
  415.                 {
  416.                     // store processed byte in the readBytes array
  417.                     int count = endIndex - startIndex;                                        
  418.                     if (readBytes == null)
  419.                     {
  420.                         readBytes = new byte[count];
  421.                         StreamHelper.BufferCopy(_dataBuffer, startIndex, readBytes, 0, count);
  422.                     }
  423.                     else
  424.                     {
  425.                         int oldSize = readBytes.Length;
  426.                         byte[] newBytes = new byte[oldSize + count];
  427.                         StreamHelper.BufferCopy(readBytes, 0, newBytes, 0, oldSize);
  428.                         StreamHelper.BufferCopy(_dataBuffer, startIndex, newBytes, oldSize, count);
  429.                         readBytes = newBytes;
  430.                     }
  431.                     // update data counters
  432.                     _dataOffset += count;
  433.                     _dataCount -= count;
  434.                     if (bufferEnd)
  435.                     {
  436.                         // we still haven't found the byte, so buffer more data
  437.                         //   and keep looking.
  438.                         BufferMoreData();
  439.                         // reset indices
  440.                         dataEnd = _dataOffset + _dataCount; // last valid byte
  441.                         startIndex = _dataOffset; // current position
  442.                         endIndex = startIndex; // current index
  443.                     }
  444.                     else
  445.                     if (foundByte)
  446.                     {
  447.                         // skip over the byte that we were looking for
  448.                         _dataOffset += 1;
  449.                         _dataCount -= 1;
  450.                     }        
  451.                 }
  452.                 else
  453.                 {
  454.                     // still haven't found character or end of buffer, so advance position
  455.                     endIndex++;
  456.                 }
  457.             }
  458.                 
  459.             return readBytes;
  460.         } // ReadToByte
  461.         protected String ReadToChar(char ch)
  462.         {
  463.             return ReadToChar(ch, null);
  464.         } // ReadToChar
  465.         protected String ReadToChar(char ch, ValidateByteDelegate validator)
  466.         {
  467.             byte[] strBytes = ReadToByte((byte)ch, validator);
  468.             if (strBytes == null)
  469.                 return null;
  470.             if (strBytes.Length == 0)
  471.                 return String.Empty;
  472.                 
  473.             String str = Encoding.ASCII.GetString(strBytes);
  474.             return str;
  475.         } // ReadToChar
  476.         public String ReadToEndOfLine()
  477.         {
  478.             String str = ReadToChar('/r');
  479.             if (ReadByte() == '/n')
  480.                 return str;
  481.             else
  482.                 return null;
  483.         } // ReadToEndOfLine        
  484.                
  485.     
  486.     } // SocketHandler
  487. // namespace System.Runtime.Remoting.Channels
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值