6 Wcf使用Stream传输
1.创建service和client项目
service项目新建wcf服务文件 MediaService 和 IMediaService
IMediaService 代码为
1 using System.IO; 2 using System.ServiceModel; 3 4 namespace Wcf_Stream_Service 5 { 6 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IMediaService”。 7 [ServiceContract] 8 public interface IMediaService 9 { 10 [OperationContract] 11 string[] GetMediaList(); 12 13 [OperationContract] 14 Stream GetMedia(string mediaName); 15 } 16 }
MediaService 代码为
1 using System; 2 using System.IO; 3 4 namespace Wcf_Stream_Service 5 { 6 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的类名“MediaService”。 7 public class MediaService : IMediaService 8 { 9 public Stream GetMedia(string mediaName) 10 { 11 string filePath = @"F:\Projects\Learn4Soft\Wcf_Stream_Service\bin\Debug\" + mediaName + ".txt"; 12 if (!File.Exists(filePath)) 13 { 14 throw new Exception("不存在文件"); 15 } 16 Stream s = null; 17 try 18 { 19 s = new FileStream(filePath, FileMode.Open, FileAccess.Read); 20 } 21 catch (Exception) 22 { 23 //如果发生异常了 我们就将流关闭释放 24 s.Close(); 25 } 26 return s; 27 } 28 29 public string[] GetMediaList() 30 { 31 string[] mediaList = new string[3]; 32 mediaList[0] = "lemon tree"; 33 mediaList[1] = "yesterday"; 34 mediaList[2] = "500 miles"; 35 return mediaList; 36 } 37 } 38 }
service服务对应的app.Config内容为:
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" /> </startup> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior name=""> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> </behaviors> <!--bindings节点为自己新增的,旨在添加两个Streamed的传输,另外设置了最长信息接收量 最后为binding定义了一个名字--> <bindings> <basicHttpBinding> <binding name="newBasicHttpBinding" transferMode="Streamed" maxReceivedMessageSize="200000" /> </basicHttpBinding> <netTcpBinding> <binding name="newNetTcpBinding" transferMode="Streamed" maxReceivedMessageSize="200000"> <!--设置无安全--> <security mode ="None" /> </binding> </netTcpBinding> </bindings> <services> <service name="Wcf_Stream_Service.MediaService"> <!--端点取了名字 以及制定了bindingConfiguration--> <endpoint address="" binding="basicHttpBinding" bindingConfiguration="newBasicHttpBinding" name="basicHttpBinding_IMetadataExchange" contract="Wcf_Stream_Service.IMediaService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="" binding="netTcpBinding" bindingConfiguration="newNetTcpBinding" name="NetTcpBinding_IMetadataExchange" contract="Wcf_Stream_Service.IMediaService" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="http://localhost:8733/MediaService" /> <!--为tcp协议定义一个地址--> <add baseAddress="net.tcp://localhost:8734/tcp" /> </baseAddresses> </host> </service> </services> </system.serviceModel> </configuration>
最后是service类的main方法:
1 using System; 2 using System.ServiceModel; 3 4 namespace Wcf_Stream_Service 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 ServiceHost host = new ServiceHost(typeof(MediaService)); 11 host.Open(); 12 Console.WriteLine("服务已经启动"); 13 Console.ReadKey(); 14 } 15 } 16 }
2 接下来是client
首先以管理员身份启动service,然后引用这个服务引用自动在配置文件中生成了对应的wcf服务配置
最后直接就是main方法
1 using System; 2 using System.IO; 3 4 namespace Wcf_Stream_Client 5 { 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 ServiceReference_Stream.MediaServiceClient client = new ServiceReference_Stream.MediaServiceClient("NetTcpBinding_IMetadataExchange"); 11 string mediaName=client.GetMediaList()[1]; 12 Console.WriteLine(mediaName); 13 14 Stream s = client.GetMedia(mediaName); 15 //var num = s.Length; 16 byte[] bytes = new byte[1000]; 17 s.Read(bytes, 0, bytes.Length); 18 //s.Seek(0, SeekOrigin.Begin); 19 20 FileStream fs = new FileStream("new_" + mediaName + ".txt", FileMode.Create); 21 BinaryWriter writer = new BinaryWriter(fs); 22 writer.Write(bytes); 23 writer.Close(); 24 fs.Close(); 25 Console.ReadKey(); 26 } 27 } 28 }
特别要备注的一点是:流传输并不是一定非要让接口请求的方法的返回值的Stream类型,什么类型都可以,只是他们在传输过程中会变成流,接收后按照协议栈又会从流转成方法返回值对应的类型。如果不按流传输,按buffer传输,我们也没有将返回值转成byte不是吗!