C# 我如何实现WCF流式处理操作,将数据流化、处理、流回(使用MessageContracts)?
我需要一个WCF服务操作来接受一个大的流,处理它并返回那个流 我用它作为我需要的参考。我听从了那篇文章中的建议 提前提问:C# 我如何实现WCF流式处理操作,将数据流化、处理、流回(使用MessageContracts)?,c#,.net,wcf,stream,messagecontract,C#,.net,Wcf,Stream,Messagecontract,我需要一个WCF服务操作来接受一个大的流,处理它并返回那个流 我用它作为我需要的参考。我听从了那篇文章中的建议 提前提问: 我想知道,当我在合同中指定返回类型时,为什么生成的服务操作没有返回类型? 如果这是预期行为,我应该如何让它在流上传递并返回已处理的流? 详细信息: 因为我需要用元数据伴随输入流和返回流,所以我根据需要用MessageContract属性修饰了这些类 以下是我的实现的简要概述: 消息契约: [MessageContract] public class InputStreamM
[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
,您可以有一个,而且只有一个参数(原始流
,或者消息契约中的某个组合)。哦,我明白了……所以您基本上不想将其分为三个步骤:上传(停止)、处理数据(停止)、下载数据,对吗?我已经用我的一些代码更新了我的帖子,但是我没有意识到你想要的东西比我实现的还要多。恐怕我不知道如何实现您需要的场景。