现在再尝试使用WCF传送文件!
虽然我知道可以使用流模型更好的实现,但现在我想尝试一下普通的方法
以下是我的服务端:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.Xml;
using WCF_file_interfaces;
namespace WCF_file_Service
{
    class Program : interfaces
    {
        static void Main(string[] args)
        {
            ServiceHost service = new ServiceHost(typeof(Program));
            service.AddServiceEndpoint(typeof(interfaces),new NetTcpBinding(), "net.tcp://192.168.18.100:8000");
            ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
            sm.HttpGetEnabled = true;
            sm.HttpGetUrl = new Uri("http://192.168.18.100:8080");
            service.Description.Behaviors.Add(sm);
            service.Open();
            Console.WriteLine("服务启动成功!");
            while (true)
            {
                string r = Console.ReadLine();
                if (r == "end")
                    break;
            }
            service.Close();
        }
        public bool file(byte[] by, string url)
        {
            FileStream fs = new FileStream(url,FileMode.CreateNew);
            try
            {
                fs.Write(by, 0, by.Length - 1);
                return true;
            }
            catch (Exception) { return false; }
            finally { fs.Close(); }
        }
    }
}客户端:string fileurl;
        private void button2_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                label1.Text = openFileDialog1.FileName;
                fileurl = openFileDialog1.FileName;
            }
        }        private void button1_Click(object sender, EventArgs e)
        {
            FileStream fs = new FileStream(fileurl, FileMode.Open);
            byte[] by = new byte[fs.Length - 1];
            fs.Read(by, 0, by.Length);
            interfacesClient service = new interfacesClient();
            try
            {
                service.Open();
                bool OK = service.file(by, @"D:\1.txt");
                if (OK == true)
                    MessageBox.Show("成功!");
                else
                    MessageBox.Show("失败!");
            }
            catch (Exception ex) { MessageBox.Show(ex.Message,"client"); }
            finally { service.Abort(); fs.Close(); }
        }服务端配置文件:<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <netTcpBinding>
                <binding name="NetTcpBinding_interfaces" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
                    hostNameComparisonMode="StrongWildcard" listenBacklog="10"
                    maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10"
                    maxReceivedMessageSize="2147483647">
                    <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647"
                        maxBytesPerRead="4096" maxNameTableCharCount="2147483647" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Transport">
                        <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
                        <message clientCredentialType="Windows" />
                    </security>
                </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="net.tcp://192.168.18.100:8000/" binding="netTcpBinding"
                bindingConfiguration="NetTcpBinding_interfaces" contract="ServiceReference_file.interfaces"
                name="NetTcpBinding_interfaces">
                <identity>
                    <userPrincipalName value="F5A6481BD70C427\Administrator" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>再传送几K的数据的时候没问题,但是如果数据达到50K的时候就会出错:超出最大数组长度配额(16384),说可以修改maxArrayLength来增加配额,但我现在已经修改成2147483647了却还是不行?有查了下资料说还要同时修改客户端的配置文件,可是客户端的配置文件在哪?我怎么没找到?我只是对客户端程序进行了“填加服务引用”操作,然后生成了一个APP。CONFIG的配置文件,这个应该是服务端的还是客户端的呢?
求解答疑惑,谢谢!!!

解决方案 »

  1.   

     <readerQuotas maxStringContentLength="20971520" maxArrayLength="20971520"/>
    客户端配置文件:
          <readerQuotas maxDepth="32" maxStringContentLength="20971520" maxArrayLength="20971520" maxBytesPerRead="40960" maxNameTableCharCount="163840"/>maxBufferPoolSize="524288",从通道接收消息的最大缓存数量
    maxBufferSize="65536" 从通道接收消息的缓存大小
    maxConnections="10" 最大连接数目
    maxReceivedMessageSize="65536">最大接收的消息大小
    maxDepth="32" 最大节点深度
    maxStringContentLength="8192" 最大内容长度
    maxArrayLength="16384"最大数组长度
    maxBytesPerRead="4096" 最大每次读取长度
    maxNameTableCharCount="16384"最大NameTableChar的数量
      

  2.   

    1、服务
    IStreamed.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;using System.ServiceModel;
    using System.IO;namespace WCF.ServiceLib.Message
    {
        /**//// <summary>
        /// 消息契约(定义与 SOAP 消息相对应的强类型类)
        /// </summary>
        [MessageContract]
        public class FileWrapper
        {
            /**//// <summary>
            /// 指定数据成员为 SOAP 消息头
            /// </summary>
            [MessageHeader]
            public string FilePath;        /**//// <summary>
            /// 指定将成员序列化为 SOAP 正文中的元素
            /// </summary>
            [MessageBodyMember]
            public Stream FileData;
        }    /**//// <summary>
        /// IStreamed接口
        /// </summary>
        [ServiceContract]
        public interface IStreamed
        {
            /**//// <summary>
            /// 上传文件
            /// </summary>
            /// <res>
            /// 1、支持数据流传输的绑定有:BasicHttpBinding、NetTcpBinding 和 NetNamedPipeBinding
            /// 2、流数据类型必须是可序列化的 Stream 或 MemoryStream
            // /3、传递时消息体(Message Body)中不能包含其他数据,即参数中只能有一个System.ServiceModel.MessageBodyMember
            /**//// </res>
            /// <param name="fileWrapper">WCF.ServiceLib.Message.FileWrapper</param>
            [OperationContract]
            void UploadFile(FileWrapper fileWrapper);
        }
    }Streamed.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;using System.ServiceModel;
    using System.IO;namespace WCF.ServiceLib.Message
    {
        /**//// <summary>
        /// IStreamed类
        /// </summary>
        public class Streamed : IStreamed
        {
            /**//// <summary>
            /// 上传文件
            /// </summary>
            /// <param name="fileWrapper">WCF.ServiceLib.Message.FileWrapper</param>
            public void UploadFile(FileWrapper fileWrapper)
            {
                var sourceStream = fileWrapper.FileData;            var targetStream = new FileStream(fileWrapper.FilePath,
                    FileMode.Create,
                    FileAccess.Write,
                    FileShare.None);            var buffer = new byte[4096];
                var count = 0;            while ((count = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    targetStream.Write(buffer, 0, count);
                }            targetStream.Close();
                sourceStream.Close();
            }
        }
    }
      

  3.   

    2、宿主
    Streamed.cs
    using (ServiceHost host = new ServiceHost(typeof(WCF.ServiceLib.Message.Streamed)))
    {
        host.Open();    Console.WriteLine("服务已启动(WCF.ServiceLib.Message.Streamed)");
        Console.WriteLine("按<ENTER>停止服务");
        Console.ReadLine();}
    App.config
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <services>
          <!--name - 提供服务的类名-->
          <!--behaviorConfiguration - 指定相关的行为配置-->
          <service name="WCF.ServiceLib.Message.Streamed" behaviorConfiguration="MessageBehavior">
            <!--address - 服务地址-->
            <!--binding - 通信方式-->
            <!--contract - 服务契约-->
            <!--bindingConfiguration - 指定相关的绑定配置-->
            <endpoint address="Message/Streamed" binding="netTcpBinding" contract="WCF.ServiceLib.Message.IStreamed" bindingConfiguration="StreamedBindingConfiguration" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:12345/Message/Streamed/"/>
                <add baseAddress="net.tcp://localhost:54321/"/>
              </baseAddresses>
            </host>
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="MessageBehavior">
              <!--httpGetEnabled - 使用get方式提供服务-->
              <serviceMetadata httpGetEnabled="true" />
              <serviceDebug includeExceptionDetailInFaults="true"/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <bindings>
          <netTcpBinding>
              <!--transferMode - 指示通道是使用流处理模式还是缓冲模式来传输请求和响应消息-->
              <!--maxReceivedMessageSize - 在采用此绑定配置的通道上可接收的最大消息大小(单位:字节)-->
              <!--receiveTimeout - 在传输引发异常之前可用于完成读取操作的时间间隔-->
              <binding name="StreamedBindingConfiguration" transferMode="Streamed" maxReceivedMessageSize="1073741824" receiveTimeout="00:10:00" />
          </netTcpBinding>
        </bindings>
      </system.serviceModel>
    </configuration>3、客户端
    Streamed.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;using System.Windows.Forms;
    using System.ServiceModel;
    using System.IO;namespace Client2.Message
    {
        /**//// <summary>
        /// 演示Message.Streamed的类
        /// </summary>
        public class Streamed
        {
            /**//// <summary>
            /// 流数据上传文件
            /// </summary>
            /// <param name="source">源文件地址</param>
            /// <param name="destination">目标路径</param>
            public void HelloStreamed(string source, string destination)
            {
                try
                {
                    var proxy = new MessageSvc.Streamed.StreamedClient();                var sr = new System.IO.FileStream(
                        source, System.IO.FileMode.Open);                proxy.UploadFile(destination + Path.GetFileName(source), sr);                sr.Close();
                    proxy.Close();                MessageBox.Show("上传成功");
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
        }
    }App.config
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <system.serviceModel>
        <client>
          <!--address - 服务地址-->
          <!--binding - 通信方式-->
          <!--contract - 服务契约-->
          <endpoint address="net.tcp://localhost:54321/Message/Streamed" binding="netTcpBinding" contract="MessageSvc.Streamed.IStreamed" bindingConfiguration="StreamedBindingConfiguration" />
        </client>
        <bindings>
          <netTcpBinding>
              <!--transferMode - 指示通道是使用流处理模式还是缓冲模式来传输请求和响应消息-->
              <!--sendTimeout - 在传输引发异常之前可用于完成写入操作的时间间隔-->
              <binding name="StreamedBindingConfiguration" transferMode="Streamed" sendTimeout="00:10:00" />
          </netTcpBinding>
        </bindings>
      </system.serviceModel>
    </configuration>
      

  4.   

    我也奇怪,它为什么每天都可以拿一千左右的技术分,查过他的回帖记录,并没有那么多可能得分的地方,真怀疑是不是钻了CSDN的漏洞刷分的。而且他的技术真的不怎么样,基本上是别处找的答案复制上来。言归正传,楼主你改配置文件当然不行了,因为你根本没有用到配置文件啊。请仔细看你服务器端这句:
    service.AddServiceEndpoint(typeof(interfaces),new NetTcpBinding(), "net.tcp://192.168.18.100:8000");
    你是新建了一个NetTcpBinding来使用,并没有指定它的任何属性,也就是说,你的NetTcpBinding是用了默认配置。正确的写法应该这样:NetTcpBinding netbinding = new NetTcpBinding();
    netbinding.MaxBufferPoolSize = int.MaxValue;
    netbinding.MaxBufferSize = int.MaxValue;
    XmlDictionaryReaderQuotas readerQuotas = new XmlDictionaryReaderQuotas();
    readerQuotas.MaxArrayLength = int.MaxValue;
    readerQuotas.MaxStringContentLength = int.MaxValue;
    readerQuotas.MaxBytesPerRead = int.MaxValue;
    netbinding.ReaderQuotas = readerQuotas;
    service.AddServiceEndpoint(typeof(interfaces),netbinding, "net.tcp://192.168.18.100:8000");
    另外你给的APP.CONFIG文件是客户端的,你的服务器端并没有使用到配置文件。判断方法之一:看<client></client>标签。服务器端的是用<services></services>标签的。客户端只要修改配置文件即可,那个你自己改吧,应该没有问题的。
      

  5.   

    谢谢,我现在正在尝试流模型,但是却又碰到了问题:套接字连接已中止。这可能是由于处理消息时出错或远程主机超过接收超时或者潜在的网络资源问题导致的。本地套接字超时是
    我已经对服务端做了如下设置:NetTcpBinding bin = new NetTcpBinding();
                bin.ReceiveTimeout = new TimeSpan(10, 10, 10);
                service.AddServiceEndpoint(typeof(interfaces), bin, "net.tcp://192.168.18.100:8000");但是却还是不行……
      

  6.   

    TO #7楼:
    你仍旧配置错误,你这样是服务器端使用默认的缓存模式,客户端被你改为了流模式,出现了模式的不匹配,所以才会提示那个错误。另外,流模式下设置超时是没有意义的,因为不有超时的可能,流模式不支持会话,只能PerCall模式,没有会话就不会超时了。
    服务端的正确的写法应该是这样:NetTcpBinding netbinding = new NetTcpBinding();
    netbinding.MaxBufferPoolSize = int.MaxValue;
    netbinding.MaxBufferSize = int.MaxValue;
    netbinding.TransferMode = TransferMode.Streamed;//这里指定传输为流传输模式。
    XmlDictionaryReaderQuotas readerQuotas = new XmlDictionaryReaderQuotas();
    readerQuotas.MaxArrayLength = int.MaxValue;
    readerQuotas.MaxStringContentLength = int.MaxValue;
    readerQuotas.MaxBytesPerRead = int.MaxValue;
    netbinding.ReaderQuotas = readerQuotas;
    service.AddServiceEndpoint(typeof(interfaces),netbinding, "net.tcp://192.168.18.100:8000");
    还是那句话,客户端你用的是配置文件,配置文件你应该会改的吧,我就不管那部分了。
      

  7.   

    有关流模式传输文件支持分段传输的方案,我写过一篇Blog,也算是我的处女作吧,暂时没打算继续写下去。
    http://www.cnblogs.com/qldsrx/
      

  8.   

    嗯,非常感谢,但是为什么我引用了system.xml,却还是没有XmlDictionaryReaderQuotas?我已经填加了对system.xml的引用
      

  9.   

    非常感谢!问题已经解决!
    但还需要添加netbinding.MaxReceivedMessageSize = int.MaxValue;
    否则会报MaxBufferSize 必须不能超过 MaxReceivedMessageSize异常,另外还需要引用using System.Runtime.Serialization;并且在引用中也要对System.Runtime.Serialization进行引用!
      

  10.   

    顺便请各位推荐下WCF方面的书!谢谢了!
      

  11.   

    远程服务器返回了意外响应: (400) Bad Request。
    我的错误是不是你们都遇见过啊 具体怎么解决呢