TcpSocketManager.cs

本文介绍了一个基于 .NET 的 TCP Socket 处理类的设计与实现细节,包括如何读取和验证协议前缀、版本号及操作代码,如何处理自定义头部信息,以及如何解析和构造计数字符串。

摘要生成于 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:       TcpSocketManager.cs
  17. //
  18. //  Summary:    Provides a base for the client and server tcp socket 
  19. //              managers.
  20. //
  21. //==========================================================================
  22. using System;
  23. using System.Collections;
  24. using System.Globalization;
  25. using System.IO;
  26. using System.Net;
  27. using System.Net.Sockets;
  28. using System.Runtime.Remoting.Messaging;
  29. using System.Text;
  30. using System.Threading;
  31. namespace System.Runtime.Remoting.Channels.Tcp
  32. {
  33.     // A client socket manager instance should encapsulate the socket
  34.     //   for the purpose of reading a response
  35.     internal abstract class TcpSocketHandler : SocketHandler
  36.     {            
  37.         private static byte[] s_protocolPreamble = Encoding.ASCII.GetBytes(".NET");
  38.         private static byte[] s_protocolVersion1_0 = new byte[]{1,0};
  39.         public TcpSocketHandler(Socket socket) : this(socket, null)
  40.         {          
  41.         } // TcpSocketHandler    
  42.     
  43.         public TcpSocketHandler(Socket socket, RequestQueue requestQueue) : base(socket, requestQueue)
  44.         {          
  45.         } // TcpSocketHandler    
  46.         private void ReadAndMatchPreamble()
  47.         {
  48.             // make sure that the incoming data starts with the preamble
  49.             InternalRemotingServices.RemotingAssert(
  50.                 s_protocolPreamble.Length == 4, 
  51.                 "The preamble is supposed to be 4 bytes ('.NET'). Somebody changed it...");
  52.             if (ReadAndMatchFourBytes(s_protocolPreamble) == false)
  53.             {
  54.                 throw new RemotingException(
  55.                     CoreChannel.GetResourceString("Remoting_Tcp_ExpectingPreamble"));
  56.             }
  57.         } // ReadAndMatchPreamble
  58.         protected void WritePreambleAndVersion(Stream outputStream)
  59.         {
  60.             outputStream.Write(s_protocolPreamble, 0, s_protocolPreamble.Length);
  61.             outputStream.Write(s_protocolVersion1_0, 0, s_protocolVersion1_0.Length);
  62.         } // WritePreamble
  63.         protected void ReadVersionAndOperation(out UInt16 operation)
  64.         {
  65.             // check for the preamble
  66.             ReadAndMatchPreamble();
  67.         
  68.             // Check the version number.
  69.             byte majorVersion = (byte)ReadByte();
  70.             byte minorVersion = (byte)ReadByte();
  71.             if ((majorVersion != 1) || (minorVersion != 0))
  72.             {
  73.                 throw new RemotingException(
  74.                     String.Format(
  75.                         CoreChannel.GetResourceString("Remoting_Tcp_UnknownProtocolVersion"),
  76.                         majorVersion.ToString() + "." + minorVersion.ToString()));
  77.             }
  78.             // Read the operation
  79.             operation = ReadUInt16();
  80.         } // ReadVersionAndOperation
  81.         protected void ReadContentLength(out bool chunked, out int contentLength)
  82.         {        
  83.             contentLength = -1;
  84.         
  85.             UInt16 header = ReadUInt16();
  86.             if (header == TcpContentDelimiter.Chunked)
  87.             {
  88.                 chunked = true;
  89.             }
  90.             else
  91.             if (header == TcpContentDelimiter.ContentLength)
  92.             {
  93.                 chunked = false;
  94.                 contentLength = ReadInt32();
  95.             }
  96.             else
  97.             {
  98.                 throw new RemotingException(
  99.                     String.Format(
  100.                         CoreChannel.GetResourceString("Remoting_Tcp_ExpectingContentLengthHeader"),
  101.                         header.ToString()));
  102.                     
  103.             }            
  104.         } // ReadContentLength 
  105.         protected void ReadToEndOfHeaders(BaseTransportHeaders headers)
  106.         {
  107.             bool bError = false;
  108.             String statusPhrase = null
  109.         
  110.             UInt16 headerType = ReadUInt16();
  111.             while (headerType != TcpHeaders.EndOfHeaders)
  112.             {
  113.                 if (headerType == TcpHeaders.Custom)
  114.                 {
  115.                     String headerName = ReadCountedString();
  116.                     String headerValue = ReadCountedString();
  117.                     headers[headerName] = headerValue;
  118.                 }
  119.                 else
  120.                 if (headerType == TcpHeaders.RequestUri)
  121.                 {         
  122.                     ReadAndVerifyHeaderFormat("RequestUri", TcpHeaderFormat.CountedString);
  123.                 
  124.                     // read uri (and make sure that no channel specific data is present)
  125.                     String uri = ReadCountedString();
  126.                     
  127.                     String channelURI;
  128.                     String objectURI;
  129.                     channelURI = TcpChannelHelper.ParseURL(uri, out objectURI);
  130.                     if (channelURI == null)
  131.                         objectURI = uri;              
  132.             
  133.                     headers.RequestUri = objectURI;
  134.                 }
  135.                 else
  136.                 if (headerType == TcpHeaders.StatusCode)
  137.                 {
  138.                     ReadAndVerifyHeaderFormat("StatusCode", TcpHeaderFormat.UInt16);
  139.                     
  140.                     UInt16 statusCode = ReadUInt16();
  141.                     // We'll throw an exception here if there was an error. If an error
  142.                     //   occurs above the transport level, the status code will still be
  143.                     //   success here.
  144.                     if (statusCode != TcpStatusCode.Success)
  145.                         bError = true;
  146.                 }
  147.                 else
  148.                 if (headerType == TcpHeaders.StatusPhrase)
  149.                 {
  150.                     ReadAndVerifyHeaderFormat("StatusPhrase", TcpHeaderFormat.CountedString);
  151.                 
  152.                     statusPhrase = ReadCountedString();
  153.                 }
  154.                 else
  155.                 if (headerType == TcpHeaders.ContentType)
  156.                 {
  157.                     ReadAndVerifyHeaderFormat("Content-Type", TcpHeaderFormat.CountedString);
  158.                 
  159.                     String contentType = ReadCountedString();
  160.                     headers.ContentType = contentType;
  161.                 }
  162.                 else
  163.                 {
  164.                     // unknown header: Read header format and ignore rest of data
  165.                     byte headerFormat = (byte)ReadByte();
  166.                     switch (headerFormat)
  167.                     {
  168.                     case TcpHeaderFormat.Void: break;
  169.                     case TcpHeaderFormat.CountedString: ReadCountedString(); break;
  170.                     case TcpHeaderFormat.Byte: ReadByte(); break;
  171.                     case TcpHeaderFormat.UInt16: ReadUInt16(); break;
  172.                     case TcpHeaderFormat.Int32: ReadInt32(); break;
  173.                     default:
  174.                     {
  175.                         // unknown format
  176.                         throw new RemotingException(
  177.                             String.Format(
  178.                                 CoreChannel.GetResourceString("Remoting_Tcp_UnknownHeaderType"),
  179.                                 headerType, headerFormat));
  180.                     }
  181.                     
  182.                     } // switch (format)
  183.                 
  184.                 }
  185.                 // read next header token
  186.                 headerType = ReadUInt16();
  187.             } // loop until end of headers         
  188.             // if an error occurred, throw an exception
  189.             if (bError)
  190.             {
  191.                 if (statusPhrase == null)
  192.                     statusPhrase = "";
  193.                     
  194.                 throw new RemotingException(
  195.                     String.Format(
  196.                         CoreChannel.GetResourceString("Remoting_Tcp_GenericServerError"),
  197.                         statusPhrase));
  198.             }
  199.         } // ReadToEndOfHeaders
  200.         protected void WriteHeaders(ITransportHeaders headers, Stream outputStream)
  201.         {
  202.             IEnumerator it = null;
  203.             BaseTransportHeaders wkHeaders = headers as BaseTransportHeaders;
  204.             if (wkHeaders != null)
  205.             {
  206.                 // write out well known headers
  207.                 //   NOTE: RequestUri is written out elsewhere.
  208.             
  209.                 if (wkHeaders.ContentType != null)
  210.                 {
  211.                     WriteContentTypeHeader(wkHeaders.ContentType, outputStream);
  212.                 }
  213.                 it = wkHeaders.GetOtherHeadersEnumerator();
  214.             }
  215.             else
  216.             {
  217.                 it = headers.GetEnumerator();
  218.             }
  219.         
  220.             // write custom headers
  221.             if (it != null)
  222.             {
  223.                 while (it.MoveNext())
  224.                 {
  225.                     DictionaryEntry header = (DictionaryEntry)it.Current;
  226.             
  227.                     String headerName = (String)header.Key;
  228.                     if (!StringHelper.StartsWithDoubleUnderscore(headerName)) // exclude special headers
  229.                     {
  230.                         String headerValue = header.Value.ToString();
  231.                         if (wkHeaders == null)
  232.                         {
  233.                             if (String.Compare(headerName, "Content-Type"true, CultureInfo.InvariantCulture) == 0)
  234.                             {
  235.                                 WriteContentTypeHeader(headerValue, outputStream);
  236.                                 continue;
  237.                             }
  238.                         }
  239.                         WriteCustomHeader(headerName, headerValue, outputStream);
  240.                     }                                
  241.                 } // while (it.MoveNext())            
  242.             }
  243.             // write EndOfHeaders token
  244.             WriteUInt16(TcpHeaders.EndOfHeaders, outputStream);
  245.         } // WriteHeaders
  246.         private void WriteContentTypeHeader(String value, Stream outputStream)
  247.         {
  248.             WriteUInt16(TcpHeaders.ContentType, outputStream);
  249.             WriteByte(TcpHeaderFormat.CountedString, outputStream);  
  250.             WriteCountedString(value, outputStream);
  251.         } // WriteContentTypeHeader
  252.         private void WriteCustomHeader(String name, String value, Stream outputStream)
  253.         {
  254.             WriteUInt16(TcpHeaders.Custom, outputStream);                    
  255.             WriteCountedString(name, outputStream);
  256.             WriteCountedString(value, outputStream);
  257.         } // WriteCustomHeader
  258.         
  259.         protected String ReadCountedString()
  260.         {
  261.             // strings are formatted as follows 
  262.             // [string format (1-byte)][encoded-size (int32)][string value (encoded-size length in bytes)]
  263.             
  264.             byte strFormat = (byte)ReadByte();
  265.             int strDataSize = ReadInt32();
  266.             if (strDataSize > 0)
  267.             {
  268.                 byte[] data = new byte[strDataSize];
  269.                 // SocketHander::Read waits until it reads all requested data
  270.                 Read(data, 0, strDataSize);
  271.                 switch (strFormat)
  272.                 {
  273.                     case TcpStringFormat.Unicode:
  274.                         return Encoding.Unicode.GetString(data);
  275.                     case TcpStringFormat.UTF8:
  276.                         return Encoding.UTF8.GetString(data);
  277.                     default:
  278.                         throw new RemotingException(
  279.                             String.Format(
  280.                                 CoreChannel.GetResourceString("Remoting_Tcp_UnrecognizedStringFormat"),
  281.                                 strFormat.ToString()));
  282.                 }
  283.             }
  284.             else
  285.             {
  286.                 return null;
  287.             }
  288.         } // ReadCountedString
  289.         protected void WriteCountedString(String str, Stream outputStream)
  290.         {
  291.             // strings are formatted as follows [string length (int32)][string value (unicode)]
  292.             int strLength = 0;
  293.             if (str != null)
  294.                 strLength = str.Length;
  295.             if (strLength > 0)
  296.             {            
  297.                 byte[] strBytes = Encoding.UTF8.GetBytes(str);          
  298.                 // write string format
  299.                 WriteByte(TcpStringFormat.UTF8, outputStream);
  300.                 // write string data size
  301.                 WriteInt32(strBytes.Length, outputStream);
  302.                 
  303.                 // write string data
  304.                 outputStream.Write(strBytes, 0, strBytes.Length);  
  305.             }
  306.             else
  307.             {
  308.                 // write string format
  309.                 //   (just call it Unicode (doesn't matter since there is no data))
  310.                 WriteByte(TcpStringFormat.Unicode, outputStream);
  311.             
  312.                 // stream data size is 0.
  313.                 WriteInt32(0, outputStream);
  314.             }
  315.         } // WriteCountedString
  316.         private void ReadAndVerifyHeaderFormat(String headerName, byte expectedFormat)
  317.         {
  318.             byte headerFormat = (byte)ReadByte();
  319.             if (headerFormat != expectedFormat)
  320.             {
  321.                 throw new RemotingException(
  322.                     String.Format(
  323.                         CoreChannel.GetResourceString("Remoting_Tcp_IncorrectHeaderFormat"),
  324.                         expectedFormat, headerName));
  325.             }
  326.         } // ReadAndVerifyHeaderFormat
  327.    
  328.     } // TcpSocketHandler
  329. // namespace System.Runtime.Remoting.Channels
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值