C# 我如何实现WCF流式处理操作,将数据流化、处理、流回(使用MessageContracts)?

C# 我如何实现WCF流式处理操作,将数据流化、处理、流回(使用MessageContracts)?,c#,.net,wcf,stream,messagecontract,C#,.net,Wcf,Stream,Messagecontract,我需要一个WCF服务操作来接受一个大的流,处理它并返回那个流 我用它作为我需要的参考。我听从了那篇文章中的建议 提前提问: 我想知道,当我在合同中指定返回类型时,为什么生成的服务操作没有返回类型? 如果这是预期行为,我应该如何让它在流上传递并返回已处理的流? 详细信息: 因为我需要用元数据伴随输入流和返回流,所以我根据需要用MessageContract属性修饰了这些类 以下是我的实现的简要概述: 消息契约: [MessageContract] public class InputStreamM

我需要一个WCF服务操作来接受一个大的流,处理它并返回那个流

我用它作为我需要的参考。我听从了那篇文章中的建议

提前提问:

  • 我想知道,当我在合同中指定返回类型时,为什么生成的服务操作没有返回类型?

  • 如果这是预期行为,我应该如何让它在流上传递并返回已处理的流?

  • 详细信息

    因为我需要用元数据伴随输入流和返回流,所以我根据需要用MessageContract属性修饰了这些类

    以下是我的实现的简要概述:

    消息契约:

    [MessageContract]
    public class InputStreamMessage
    {
        [MessageHeader]
        public InputStreamHeader Header { get; set; }
    
        [MessageBodyMember(Order = 1)]
        public Stream Data { get; set; }
    
    }
    
    [MessageContract]
    public class OutputStreamMessage
    {
        [MessageHeader]
        public OutputStreamHeader Header { get; set; }
    
        [MessageBodyMember(Order = 1)]
        public Stream Data { get; set; }
    
    }
    
    [ServiceContract]
    public interface IStreamService
    {
        [OperationContract]
        OutputStreamMessage ProcessStream(InputStreamMessage input);
    }
    
     public OutputStreamMessage DoStreamOperation(InputStreamMessage input)
     {
        //Some logic that assigns re
        OutputStreamMessage output = DoSomeNonBufferedProcessing(input);
    
        return output;
     }
    
    服务合同:

    [MessageContract]
    public class InputStreamMessage
    {
        [MessageHeader]
        public InputStreamHeader Header { get; set; }
    
        [MessageBodyMember(Order = 1)]
        public Stream Data { get; set; }
    
    }
    
    [MessageContract]
    public class OutputStreamMessage
    {
        [MessageHeader]
        public OutputStreamHeader Header { get; set; }
    
        [MessageBodyMember(Order = 1)]
        public Stream Data { get; set; }
    
    }
    
    [ServiceContract]
    public interface IStreamService
    {
        [OperationContract]
        OutputStreamMessage ProcessStream(InputStreamMessage input);
    }
    
     public OutputStreamMessage DoStreamOperation(InputStreamMessage input)
     {
        //Some logic that assigns re
        OutputStreamMessage output = DoSomeNonBufferedProcessing(input);
    
        return output;
     }
    
    服务实施:

    [MessageContract]
    public class InputStreamMessage
    {
        [MessageHeader]
        public InputStreamHeader Header { get; set; }
    
        [MessageBodyMember(Order = 1)]
        public Stream Data { get; set; }
    
    }
    
    [MessageContract]
    public class OutputStreamMessage
    {
        [MessageHeader]
        public OutputStreamHeader Header { get; set; }
    
        [MessageBodyMember(Order = 1)]
        public Stream Data { get; set; }
    
    }
    
    [ServiceContract]
    public interface IStreamService
    {
        [OperationContract]
        OutputStreamMessage ProcessStream(InputStreamMessage input);
    }
    
     public OutputStreamMessage DoStreamOperation(InputStreamMessage input)
     {
        //Some logic that assigns re
        OutputStreamMessage output = DoSomeNonBufferedProcessing(input);
    
        return output;
     }
    
    客户端:

    [MessageContract]
    public class InputStreamMessage
    {
        [MessageHeader]
        public InputStreamHeader Header { get; set; }
    
        [MessageBodyMember(Order = 1)]
        public Stream Data { get; set; }
    
    }
    
    [MessageContract]
    public class OutputStreamMessage
    {
        [MessageHeader]
        public OutputStreamHeader Header { get; set; }
    
        [MessageBodyMember(Order = 1)]
        public Stream Data { get; set; }
    
    }
    
    [ServiceContract]
    public interface IStreamService
    {
        [OperationContract]
        OutputStreamMessage ProcessStream(InputStreamMessage input);
    }
    
     public OutputStreamMessage DoStreamOperation(InputStreamMessage input)
     {
        //Some logic that assigns re
        OutputStreamMessage output = DoSomeNonBufferedProcessing(input);
    
        return output;
     }
    
    在客户端,我随后生成服务引用,并调用服务,如下所示:

    private void PerformStreamOperation()
    {
        try
        {
            //
            StreamServiceReference.StreamServiceClient client = new StreamServiceReference.StreamServiceReferenceClient();
            client.Open();
    
            //Set Header and Parameters
            InputMessageHeader header = new InputMessageHeader();
    
            //...                
            //... initialize header data here
            //...                
    
            //... do some operation to get input stream
            var inputstream = SomeOperationToGetInputStream();
    
            //Perform Service stream action
            //         ____ [ Why does the generated method have the following signature, retuning void?]
            //        |     [ If this is expected, how do I use it? ]
            //        |
            //        V 
            client.DoStreamOperation(header, ref inputstream); 
    
    
            //...                
            //... Do what you wish with data
            //...                
    
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message.ToString(), "Stream Processing Error");
        }
    }
    
    MSDN文章使用的合同与

    流EchoStream(流数据)

    但没有等效MessageContract实现的示例。示例版本没有预期的返回

    更新

    • 我注意到服务引用具有使用预期方法签名生成的任务/异步方法。也许这意味着当使用带有流属性的MessageContract时,返回一个结构类似的对象,那么您必须异步调用它。我没有在任何地方看到它的记录。将尝试使用这些方法-不起作用,因为我们需要同步操作。
    • 我还尝试使用
      ChannelFactory
      作为生成的代理客户端的替代:

        EndpointAddress endpoint = new EndpointAddress("net.tcp://localhost:9910/StreamService");
      
        channelFactory = new ChannelFactory<IStreamService>("netTcpStreamedEndPoint");
        channelFactory.Endpoint.Contract.SessionMode = SessionMode.Allowed;
        IStreamService service = channelFactory.CreateChannel();
      
      EndpointAddress endpoint=新的EndpointAddress(“net”)。tcp://localhost:9910/StreamService");
      channelFactory=新的channelFactory(“netTcpStreamedEndPoint”);
      channelFactory.Endpoint.Contract.SessionMode=SessionMode.Allowed;
      IStreamService=channelFactory.CreateChannel();
      

      • 我很抱歉在回复中做出了回应(我没有评论的名声)

        我和你们一样在从事Similar项目——我有一个服务,它接受大量的数据流(使用MessageContracts),处理它,然后客户端可以下载这些数据

        首先-输入参数位于:

         client.DoStreamOperation(header, ref inputstream); 
        
        显示您似乎没有生成包含MessageContracts的服务代理(请参阅)。这将在客户端为您提供OutputStreamMessage和InputStreamMessage合同

        正确生成messageContracts后,我可以在代码中编写这两个,而不会收到编译错误:

        client.DoStreamOperation(inputStreamMessage)
        

        但基本上第一个是没有用的。 当然,我必须首先创建InputStreamMessage对象:

        StreamServiceReference.StreamServiceClient.InputStreamMessage inputStreamMessage = new StreamServiceReference.StreamServiceClient.InputStreamMessage();
        
        如果你愿意,我可以发布一些我的邮件合同样本

        另外,请看这篇文章:。在项目的早期阶段,我的messagecontracs看起来很相似


        编辑: 会话模式设置如下:

        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
        
        public void StartUpload(RemoteFileInfo fileInfo)
                {
        
                    string filePath = define your filePath, where you want to save the file;           
        
                    int chunkSize = 2048;
                    byte[] buffer = new byte[chunkSize];
        
                    using (System.IO.FileStream writeStream = new System.IO.FileStream(filePath, System.IO.FileMode.CreateNew, System.IO.FileAccess.Write))
                    {
                        do
                        {
                            // read bytes from input stream (provided by client)
                            int bytesRead =  fileInfo.FileByteStream.Read(buffer, 0, chunkSize);
                            if (bytesRead == 0) break;
        
                            // write bytes to output stream
                            writeStream.Write(buffer, 0, bytesRead);
                        } while (true);
        
                        writeStream.Close();
                    }
                }
        
        这样做的原因是我需要维护关于对象的信息(状态),这对于多个客户端来说是常见的。但这不应影响流媒体

        这是我的装订。Im使用基本http:

              <basicHttpBinding>
                <binding name="TransferBinding" transferMode="Streamed" maxReceivedMessageSize="10067108864">
                </binding>
              </basicHttpBinding>
        
        这是在客户端定义的方法体,在服务端调用StartUpload()定义(您需要定义指向要上载的文件的文件路径):

        然后,我在服务端定义StartUpload()operationContract。StartUpload合同的内部如下所示:

        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
        
        public void StartUpload(RemoteFileInfo fileInfo)
                {
        
                    string filePath = define your filePath, where you want to save the file;           
        
                    int chunkSize = 2048;
                    byte[] buffer = new byte[chunkSize];
        
                    using (System.IO.FileStream writeStream = new System.IO.FileStream(filePath, System.IO.FileMode.CreateNew, System.IO.FileAccess.Write))
                    {
                        do
                        {
                            // read bytes from input stream (provided by client)
                            int bytesRead =  fileInfo.FileByteStream.Read(buffer, 0, chunkSize);
                            if (bytesRead == 0) break;
        
                            // write bytes to output stream
                            writeStream.Write(buffer, 0, bytesRead);
                        } while (true);
        
                        writeStream.Close();
                    }
                }
        

        您是否尝试过使用
        ChannelFactory
        而不是添加服务引用,这可能有助于显示问题所在。是的,我使用过ChannelFactory。将放置一个updateOk,以及使用
        ChannelFactory
        的结果是什么,您是否尝试过打开跟踪并查看是否出现任何错误?将使用我的triedHi@JakubJ更新问题。谢谢你的回复。您介意发布一个示例实现吗?您还使用了什么
        SessionMode
        ,绑定配置如何?它是一个连续的数据流,还是您在服务操作的某个点关闭它?但是,codeproject文章不是我想要的。我想发送和返回一个连续的,不间断的流你好。你所说的连续流到底是什么意思?比如说,如果你正在流媒体直播视频?Iam使用流传输大文件-客户端选择要传输的文件,点击“上载”按钮,整个文件被流传输到服务端。我将在几分钟内更新我的答案,并提供一些实现。我的意思是没有中断。当我输入流时,它会被处理,并在运行中返回。类似于通常使用的方法签名
        void ProcessStream(流输入,流输出)
        其中
        ProcessStream
        处理并将处理后的
        输入
        流逐字节写入
        输出
        。无
        Stream.Close()
        内部操作。在一个应用程序的上下文中,这很好。但与WCF完全不同。关键是,使用
        transferMode=Streamed
        ,您可以有一个,而且只有一个参数(原始
        ,或者
        消息契约中的某个组合)。哦,我明白了……所以您基本上不想将其分为三个步骤:上传(停止)、处理数据(停止)、下载数据,对吗?我已经用我的一些代码更新了我的帖子,但是我没有意识到你想要的东西比我实现的还要多。恐怕我不知道如何实现您需要的场景。