gpt4 book ai didi

c# - 我如何实现一个 WCF 流操作,将数据传入、处理、流回(使用 MessageContracts)?

转载 作者:行者123 更新时间:2023-11-30 17:44:55 26 4
gpt4 key购买 nike

我有一个 WCF 服务操作的要求,它接受一个大流,处理它并返回该流。

我用了an MSDN article on Large Data Streaming作为我需要的引用。我遵循了那篇文章中的建议。

提前提出问题:

  1. 我想知道为什么生成的服务操作在合约中指定时没有返回类型?

  2. 如果这是预期的行为,我应该如何让它传递一个流并返回一个处理过的流?

详细信息:

因为我需要用元数据伴随输入和返回流,所以我根据需要用 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; }

}

服务契约(Contract):

[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 文章使用了与 official WCF samples. 中存在的完全相同的契约(Contract)

Stream EchoStream(Stream data)

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

更新

  • 我注意到服务引用具有使用预期方法签名生成的任务/异步方法。也许这意味着当使用带有 Stream 属性的 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();

最佳答案

很抱歉在回答中回复(我没有评论的声誉)。

我和你一样在做类似的项目 - 我有服务,它接受大量数据流(使用 MessageContracts),处理它,然后客户端可以下载这些数据。

首先 - 输入参数位于:

 client.DoStreamOperation(header, ref inputstream); 

显示,您似乎没有生成包含 MessageContracts 的服务代理(请参阅 http://blogs.msdn.com/b/zainnab/archive/2008/05/13/windows-communication-foundation-wcf-what-the-hell-is-always-generate-message-contracts.aspx)。那应该在客户端为您提供 OutputStreamMessage 和 InputStreamMessage 契约(Contract)。

通过正确生成消息合约,我可以在我的代码中编写这两个,而不会收到编译错误:

client.DoStreamOperation(inputStreamMessage)

   StreamServiceReference.StreamServiceClient.OutputStreamMessage outputMessage = client.DoStreamOperation(inputStreamMessage)

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

StreamServiceReference.StreamServiceClient.InputStreamMessage inputStreamMessage = new StreamServiceReference.StreamServiceClient.InputStreamMessage();

如果您愿意,我可以发布一些我的 MessageContracts 示例。

另外,请看这篇文章:http://www.codeproject.com/Articles/166763/WCF-Streaming-Upload-Download-Files-Over-HTTP .我的消息契约(Contract)在项目的早期阶段看起来很相似


编辑: session 模式设置如下:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]

这样做的原因是我需要维护关于对象的信息(状态),这些信息对于多个客户端是通用的。但这应该不会影响流式传输。

这是我的绑定(bind)。我正在使用基本的 http:

      <basicHttpBinding>
<binding name="TransferBinding" transferMode="Streamed" maxReceivedMessageSize="10067108864">
</binding>
</basicHttpBinding>

对于上传,我使用这种消息合约:

    [MessageContract]
public class RemoteFileInfo : IDisposable
{
[MessageHeader(MustUnderstand = true)]
public string FileName;

[MessageBodyMember]
public System.IO.Stream FileByteStream;
}

这是客户端定义的方法体,调用服务端定义的StartUpload()(你需要定义指向你要上传的文件的文件路径):

using (System.IO.FileStream stream = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read))
{
// start service client
CalculationServiceClient client = new CalculationServiceClient();

RemoteFileInfo remoteFileInfo = new RemoteFileInfo(); ;
remoteFileInfo.FileName = TextBox1.Text;
remoteFileInfo.FileByteStream = stream;

// upload file
client.StartUpload(remoteFileInfo);

// close service client
client.Close();
uploadStream.Close();
}
}

然后,我在服务端定义 StartUpload() operationContract。 StartUpload 契约(Contract)的内部看起来像这样:

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();
}
}

关于c# - 我如何实现一个 WCF 流操作,将数据传入、处理、流回(使用 MessageContracts)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28829108/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com