1.發現WCF默認不支持原始字節流傳輸, 即訪問WCF的Server端的消息都已被MSFT封裝(內部是xml),即使用各種MessageEncoder也不可以, WCF會把需要傳輸的數據封裝到xml的body部分。
2.經過試驗, 想要實現傳輸原始字節流, 從下到上必須實現自定義IChannel,自定義ChannelBase,自定義RequestContext,自定義Listener和Factory,自定義TransportBindingElement,自定義MessageEncoder,自定義MessageEncoderFactory,自定義MessageEncoderBindingElement, 自定義Binding,以上部分組合即可以實現Channel級接受原始數據。
3.如果想要把自定義Channel的實現封裝成Endpoint, 還需要實現ChannelDispatcherBase和ServiceHostBase
4.如果WCF宿主在Windows服務或者IIS中,還需要實現ServiceHostFatoryBase
實現過程中需要註意幾點:
1.默認Channel都是Message結構, 即WCF封裝的消息結構,無法接受原始數據流, 因此必須實現自定義Channel。
2.如果實現自定義Channel,則默認的Endpoint不支持此Channel, 因為ServiceHost內部默認調用DispatcherBuilder 的 GetSupportedChannelTypes, 此方法返回默認的幾個Channel, 比如IReplyChannel,IRequestChannel,IInputChannel等等。
3.可以利用Behavior來對Service,Endpoint,Contract等等各個級別進行過濾, 需要利用MessageFilter
4.使用Behavior時, 在調用Service的Open方法之前加入。
5.在實現ServiceHostBase時,重載的CreateDescription必須返回新的ServiceDescription。另外out IDictionary<string, ContractDescription> implementedContracts 的輸出參數也必須實現, 基本思路就是根據要加入的Service類型,反射後得到利用ContractDescription.GetContract得到Service聲明的接口的各個ContractDescription,然後添加到字典裏。字典的key為ContractDescription.ConfigurationName
6.在實現ServiceHostBase時, 構造裏必須調用InitializeDescription(new UriSchemeKeyedCollection(baseAddresses));, 不然後續的AddServiceEndpoint會失敗。
7.自定義實現的此原始Socket數據流Channel的ServiceHost可能和其他的默認ServiceHost有沖突, 無法***存, 即此ServiceHost只能監聽自定義Channel而無法初始化默認Channel的BuildChannelListener。 解決辦法是:(1)創建2個ServcieHost, 比如PIX,壹個ServiceHost支持V2,另壹個支持V3. (2)就是在ServiceHost的InitializeRuntime裏調用Base.InitializeRuntime,但是由於此方法會把Endpoints裏的所有channel都初始化,而系統不支持其他自定義Channel接口,導致初始化失敗。使用此方法時就需要把自定義channel的endpoint放到最後調用AddServiceEndpoint。然後在出現異常時, 主動調用自定義Binding的BuildChannelListener,然後通過自定義ChannelDispatcher,把Listener放到ServiceHost裏。
8.在實現自定義ChannelBase時, 內部使用TcpListener和TcpClient來接受Client發來的請求,然後利用NetworkStream來解析byte數組。BufferManager來負責數據的緩沖區。
9.實現自定義Router時, 即把接受字節流路由到對應方法時, 可以根據自己業務規則, 解析字節流, 然後根據ServiceHost.Description.Endpoints的ContractDescription.Operations獲取對應方法後, 調用傳參。