[英]Can't send streamed data from client to server via WCF
I'm trying to send some data from client to server using streaming functionality in WCF.我正在尝试使用 WCF 中的流功能将一些数据从客户端发送到服务器。 I can read stream returned from server with no issues.
我可以毫无问题地读取从服务器返回的流。 Other way around doesn't work however.
然而,其他方式不起作用。
Tried wrapping stream in class decorated with MessageContract with no success.尝试在用 MessageContract 装饰的类中包装流,但没有成功。
Client config:客户端配置:
<bindings>
<netTcpBinding>
<binding name="streamingBinding" transferMode="Streamed"
maxReceivedMessageSize="5000000000">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
Server config:服务器配置:
<bindings>
<netTcpBinding>
<binding name="streamingBinding" transferMode="Streamed"
maxReceivedMessageSize="5000000000">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
... ...
<service behaviorConfiguration="WcfSvc.WcfServiceBehavior"
name="Shared.StreamingService">
<endpoint address="" binding="netTcpBinding"
bindingConfiguration="streamingBinding"
contract="Shared.IStreamingService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexTcpBinding"
bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8733/StreamingTest/" />
</baseAddresses>
</host>
</service>
Host app:主机应用程序:
private static IStreamingService _service;
private static ServiceHost _serviceHost;
static void Main()
{
_service = new StreamingService();
_serviceHost = new ServiceHost(_service);
_serviceHost.Open();
Console.WriteLine("Press enter to read data");
Console.ReadLine();
var stream = _service.GetData();
var file = File.Create(@"PATH TO NON EXISTING FILE");
stream.CopyTo(file);
file.Close();
Console.WriteLine("Press enter to close host");
Console.ReadLine();
_serviceHost.Close();
}
Client app:客户端应用程序:
private const string EndpointAddress = "net.tcp://localhost:8733/StreamingTest/";
private const string TcpBindingConfigName = "streamingBinding";
private static WcfChannelFactory<IStreamingService> _factory = new WcfChannelFactory<IStreamingService>();
private static IStreamingService _service;
private static ICommunicationObject _communicationObject;
static void Main()
{
Console.WriteLine("Press enter to connect");
Console.ReadLine();
(_service, _communicationObject) = _factory.OpenAsync(EndpointAddress, TcpBindingConfigName).Result;
var s = File.OpenRead(@"PATH TO EXISTING FILE");
_service.SetData(s);
Console.WriteLine("Press enter to disconnect");
Console.ReadLine();
_communicationObject.Close();
}
Service:服务:
[ServiceContract(SessionMode = SessionMode.NotAllowed)]
public interface IStreamingService
{
[OperationContract]
void SetData(Stream data);
[OperationContract]
Stream GetData();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class StreamingService : IStreamingService
{
private Stream _data;
public void SetData(Stream data)
{
_data = data;
}
public Stream GetData()
{
return _data;
}
}
Channel factory implementation:通道工厂实现:
public class WcfChannelFactory<TService>
{
private ChannelFactory<TService> _channelFactory;
public async Task<(TService, ICommunicationObject)> OpenAsync(string endpointAddress, string tcpBindingConfigName)
{
var tcpBinding = new NetTcpBinding(tcpBindingConfigName);
_channelFactory = new ChannelFactory<TService>(tcpBinding);
await Task.Factory.FromAsync(_channelFactory.BeginOpen, _channelFactory.EndOpen, null);
var wcf = _channelFactory.CreateChannel(new EndpointAddress(endpointAddress));
return (wcf, wcf as ICommunicationObject);
}
public void Close()
{
_channelFactory?.Close();
_channelFactory = null;
}
}
Please fill file names at lines where file streams are created.请在创建文件流的行填写文件名。
After running host and client, pressing enter in client window and then in host window exception is thrown:运行主机和客户端后,在客户端窗口按回车,然后在主机窗口抛出异常:
System.ObjectDisposedException: Cannot access a closed Stream. System.ObjectDisposedException:无法访问关闭的流。 (on line 'stream.CopyTo(file);' in host app)
(在线'stream.CopyTo(文件);'在主机应用程序中)
Reverse scenario works just fine (sending file from server to client)反向场景工作得很好(从服务器向客户端发送文件)
I know what caused my problem.我知道是什么导致了我的问题。 The problem is here:
问题在这里:
public Stream GetData()
{
return _data;
}
After returning from GetData method WCF automatically closes the stream.从 GetData 方法返回后,WCF 自动关闭流。 To propagate the stream outside of the service class I had to use an event:
为了在服务类之外传播流,我必须使用一个事件:
public event Action<StreamMessage> DataSet;
public void SetData(StreamMessage data)
{
_data = data;
DataSet?.Invoke(data);
}
and then consume the stream in the event handler.然后在事件处理程序中使用流。
I suggest you use the Asynchronous model to build/implement the Service contract, since the file stream is not always synchronized.我建议您使用异步模型来构建/实现服务契约,因为文件流并不总是同步的。 Please refer to the below code segments.
请参考以下代码段。
[ServiceContract]
interface IService
{
[OperationContract]
Task UploadStream(Stream stream);
}
public class MyService : IService
{
public async Task UploadStream(Stream stream)
{
using (stream)
{
using (var file = File.Create(Path.Combine(Guid.NewGuid().ToString() + ".png")))
{
await stream.CopyToAsync(file);
}
}
}
}
Invocation.调用。
ServiceReference1.ServiceClient client = new ServiceReference1.ServiceClient();
string file = Path.Combine(@"C:\", "1.png");
FileStream fs = new FileStream(file,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.ReadWrite);
//var s = File.OpenRead(file);
//MemoryStream ms = new MemoryStream();
//fs.CopyTo(ms);
//ms.Position = 0;
client.UploadStream(fs);
Console.WriteLine("DOne");
Console.ReadLine();
Feel free to let me know if there is anything I can help with.如果有什么我可以帮忙的,请随时告诉我。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.