VB.NET中WCF服务使用TcpNetBinding时,为何StreamRequest无法接收数据流?

2026-05-06 12:591阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1421个文字,预计阅读时间需要6分钟。

VB.NET中WCF服务使用TcpNetBinding时,为何StreamRequest无法接收数据流?

我的第一个问题是关于温差的计算公式。以下是VS2010中.NET 4、VB.NET的最终目标是:通过TCP绑定从客户端接收(完整)流到IIS托管WCF服务。我面临的问题是该服务无法从提供的流中读取任何字节。目前有了细节。

我的第一个问题是温和的=)

以下是VS2010中的.Net 4,VB.Net.最终目标是通过Tcp绑定从客户端接收(完整)流到IIS托管WCF服务.我面临的问题是该服务无法从提供的流中读取任何字节.现在有了细节……为了简洁,我已经删除了相当数量但是,如果我省略了一些重要的东西,请告诉我.

服务合同如下:

<ServiceContract(Namespace:="ImageSystem")> _ Public Interface IUploadService <OperationContract()> _ Function UploadFile(ByVal file As ImageUpload) As ImageUpload End Interface

数据协定ImageUpload如下:

<MessageContract()> _ Public Class ImageUpload #Region " Message Header " Private _ImageID As Nullable(Of Long) <MessageHeader()> _ Public Property ImageID() As Nullable(Of Long) Get Return _ImageID End Get Set(ByVal value As Nullable(Of Long)) _ImageID = value End Set End Property '... a few other value type properties #End Region #Region " Message Body" ' Do not add any more members to the message body or streaming support will be disabled! <MessageBodyMember()> _ Public Data As System.IO.Stream #End Region End Class

相关的服务器配置/绑定如下(这些显然只是dev环境设置):

<system.serviceModel> <bindings> <netTcpBinding> <binding name="netTcpStreamBinding" transferMode="Streamed" maxBufferSize="20971520" maxReceivedMessageSize="20971520"/> </netTcpBinding> </bindings> <services> <service behaviorConfiguration="UploadServiceBehaviour" name="ImageSystem.SVC.UploadService"> <endpoint address="" binding="netTcpBinding" bindingConfiguration="netTcpStreamBinding" contract="ImageSystem.SVC.IUploadService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:809/UploadService" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="UploadServiceBehaviour"> <serviceMetadata mycomputername.mydomain/ImageSystem/UploadService.svc" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IUploadService" contract="UploadService.Local.IUploadService" name="NetTcpBinding_IUploadService"> <identity> <dns value="localhost" /> </identity> </endpoint> </client> </system.serviceModel>

客户端使用情况如下:

Public Sub Test() Dim serviceClient As UploadService.Local.UploadServiceClient = New UploadService.Local.UploadServiceClient AddHandler serviceClient.UploadFileCompleted, AddressOf LocalTestCallback Dim ms As MemoryStream = New MemoryStream My.Resources.Penguins.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) serviceClient.ClientCredentials.Windows.ClientCredential.Domain = "MYDOMAIN" serviceClient.ClientCredentials.Windows.ClientCredential.UserName = "User" serviceClient.ClientCredentials.Windows.ClientCredential.Domain = "Password123" serviceClient.UploadFileAsync(Nothing, ..., ms, ms) '"..." is obviously not actually here, other values omitted. "ms" is passed as UserState object in addition to fulfilling the 'Data' parameter End Sub

如果您想知道(或重要),企鹅图像是样本图片目录中随Windows 7提供的图像.图像为777,835字节(应在相关请求/缓冲区最大大小内).

我尝试了两种方法来在服务器端读取图像.

方法1:

Public Function UploadFile(ByVal file As ImageUpload) As ImageUpload Implements IUploadService.UploadFile Dim uploadBuffer(Helper.Settings.AppSettings(Of Integer)("UploadBufferSize", True) - 1) As Byte Dim ms As MemoryStream = New MemoryStream() Dim bytesRead As Integer Do bytesRead = file.Data.Read(uploadBuffer, 0, uploadBuffer.Length) ms.Write(uploadBuffer, 0, bytesRead) Loop Until bytesRead = 0 End Function

方法2:

Public Function UploadFile(ByVal file As ImageUpload) As ImageUpload Implements IUploadService.UploadFile Dim reader As StreamReader = New StreamReader(file.Data) Dim imageB64 As String = reader.ReadToEnd ms = New MemoryStream(Convert.FromBase64String(imageB64)) End Function

在两种情况下,ms.Length = 0.更明显,在第二种方法中,imageB64 =“”(空字符串).

为什么我从流中收到任何东西?另外,作为一个偷偷摸摸的子问题,为什么生成的代理类不提供接受ImageUpload类型对象的重载?

先感谢您!!

我觉得你会遇到你提到的问题似乎很奇怪,所以我很好奇并使用你的服务合同整理了一个实现.那个实际上是直接工作的.我实际上并不知道你的情况出了什么问题(这不是很明显),但是让我在这里发布一个有效的解决方案,希望这能帮助你解决问题.

不幸的是,由于我多年前放弃了VB,我只能提供C#代码.希望没关系.

VB.NET中WCF服务使用TcpNetBinding时,为何StreamRequest无法接收数据流?

Server Web.config(在IIS中测试,使用net.tcp绑定):

<system.serviceModel> <bindings> <netTcpBinding> <binding transferMode="Streamed" maxReceivedMessageSize="1000000"> <security mode="None"/> </binding> </netTcpBinding> </bindings> <services> <service name="ImageSystem.SVC.UploadService"> <endpoint address="" binding="netTcpBinding" contract="ImageSystem.SVC.IUploadService"> </endpoint> <endpoint address="mex" kind="mexEndpoint" binding="mexTcpBinding"/> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata localhost/WcfService1/UploadService.svc" binding="netTcpBinding" contract="ImageServices.IUploadService" name="NetTcpBinding_IUploadService"> </endpoint> </client> </system.serviceModel>

服务合同&执行:

[ServiceContract(Namespace="urn:ImageSystem")] public interface IUploadService { [OperationContract] ImageUpload UploadFile(ImageUpload file); } [MessageContract] public class ImageUpload { [MessageHeader] public long? ImageID { get; set; } [MessageBodyMember] public Stream Data; } public class UploadService : IUploadService { public ImageUpload UploadFile(ImageUpload file) { long length; using (var ms = new MemoryStream()) { file.Data.CopyTo(ms); length = ms.Length; } return new ImageUpload { ImageID = length, Data = new MemoryStream() }; } }

测试应用:

private static readonly string imgPath = @"C:\Pictures\somepicture.jpg"; private static readonly EventWaitHandle waitHandle = new AutoResetEvent(false); static void Main() { long? result; using (var service = new ImageServices.UploadServiceClient("NetTcpBinding_IUploadService")) { var image = new ImageServices.ImageUpload(); using (var imgStream = File.OpenRead(imgPath)) { image.Data = imgStream; service.UploadFileCompleted += (sender, e) => { result = e.Result; if (e.Data != null) image.Data.Dispose(); waitHandle.Set(); }; service.UploadFileAsync(null, imgStream); waitHandle.WaitOne(); } } }

首先,正如您所看到的,配置文件可以更简单.特别是大型BufferSize值不是必需的.然后,关于服务合同,我不清楚为什么上传操作会收到AND返回一个ImageUpload消息.在我的实现中,我在ImageID参数中返回上传的文件大小,当然只是为了演示目的.我不知道你的合同背后的原因是什么,以及你真正想要回归的是什么.

实际上,当我知道你的代码为什么会失败时,就要点击“发送”.在测试客户端中,在调用serviceClient.UploadFileAsync()之前,将此行添加到代码中:ms.Seek(0,SeekOrigin.Begin).

这会将MemoryStream的位置重置回其开头.如果你不这样做,MemoryStream将仅从其当前位置消耗,这是它的结束 – 这解释了服务端收到的流的长度= 0!

本文共计1421个文字,预计阅读时间需要6分钟。

VB.NET中WCF服务使用TcpNetBinding时,为何StreamRequest无法接收数据流?

我的第一个问题是关于温差的计算公式。以下是VS2010中.NET 4、VB.NET的最终目标是:通过TCP绑定从客户端接收(完整)流到IIS托管WCF服务。我面临的问题是该服务无法从提供的流中读取任何字节。目前有了细节。

我的第一个问题是温和的=)

以下是VS2010中的.Net 4,VB.Net.最终目标是通过Tcp绑定从客户端接收(完整)流到IIS托管WCF服务.我面临的问题是该服务无法从提供的流中读取任何字节.现在有了细节……为了简洁,我已经删除了相当数量但是,如果我省略了一些重要的东西,请告诉我.

服务合同如下:

<ServiceContract(Namespace:="ImageSystem")> _ Public Interface IUploadService <OperationContract()> _ Function UploadFile(ByVal file As ImageUpload) As ImageUpload End Interface

数据协定ImageUpload如下:

<MessageContract()> _ Public Class ImageUpload #Region " Message Header " Private _ImageID As Nullable(Of Long) <MessageHeader()> _ Public Property ImageID() As Nullable(Of Long) Get Return _ImageID End Get Set(ByVal value As Nullable(Of Long)) _ImageID = value End Set End Property '... a few other value type properties #End Region #Region " Message Body" ' Do not add any more members to the message body or streaming support will be disabled! <MessageBodyMember()> _ Public Data As System.IO.Stream #End Region End Class

相关的服务器配置/绑定如下(这些显然只是dev环境设置):

<system.serviceModel> <bindings> <netTcpBinding> <binding name="netTcpStreamBinding" transferMode="Streamed" maxBufferSize="20971520" maxReceivedMessageSize="20971520"/> </netTcpBinding> </bindings> <services> <service behaviorConfiguration="UploadServiceBehaviour" name="ImageSystem.SVC.UploadService"> <endpoint address="" binding="netTcpBinding" bindingConfiguration="netTcpStreamBinding" contract="ImageSystem.SVC.IUploadService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" /> <host> <baseAddresses> <add baseAddress="net.tcp://localhost:809/UploadService" /> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior name="UploadServiceBehaviour"> <serviceMetadata mycomputername.mydomain/ImageSystem/UploadService.svc" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IUploadService" contract="UploadService.Local.IUploadService" name="NetTcpBinding_IUploadService"> <identity> <dns value="localhost" /> </identity> </endpoint> </client> </system.serviceModel>

客户端使用情况如下:

Public Sub Test() Dim serviceClient As UploadService.Local.UploadServiceClient = New UploadService.Local.UploadServiceClient AddHandler serviceClient.UploadFileCompleted, AddressOf LocalTestCallback Dim ms As MemoryStream = New MemoryStream My.Resources.Penguins.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg) serviceClient.ClientCredentials.Windows.ClientCredential.Domain = "MYDOMAIN" serviceClient.ClientCredentials.Windows.ClientCredential.UserName = "User" serviceClient.ClientCredentials.Windows.ClientCredential.Domain = "Password123" serviceClient.UploadFileAsync(Nothing, ..., ms, ms) '"..." is obviously not actually here, other values omitted. "ms" is passed as UserState object in addition to fulfilling the 'Data' parameter End Sub

如果您想知道(或重要),企鹅图像是样本图片目录中随Windows 7提供的图像.图像为777,835字节(应在相关请求/缓冲区最大大小内).

我尝试了两种方法来在服务器端读取图像.

方法1:

Public Function UploadFile(ByVal file As ImageUpload) As ImageUpload Implements IUploadService.UploadFile Dim uploadBuffer(Helper.Settings.AppSettings(Of Integer)("UploadBufferSize", True) - 1) As Byte Dim ms As MemoryStream = New MemoryStream() Dim bytesRead As Integer Do bytesRead = file.Data.Read(uploadBuffer, 0, uploadBuffer.Length) ms.Write(uploadBuffer, 0, bytesRead) Loop Until bytesRead = 0 End Function

方法2:

Public Function UploadFile(ByVal file As ImageUpload) As ImageUpload Implements IUploadService.UploadFile Dim reader As StreamReader = New StreamReader(file.Data) Dim imageB64 As String = reader.ReadToEnd ms = New MemoryStream(Convert.FromBase64String(imageB64)) End Function

在两种情况下,ms.Length = 0.更明显,在第二种方法中,imageB64 =“”(空字符串).

为什么我从流中收到任何东西?另外,作为一个偷偷摸摸的子问题,为什么生成的代理类不提供接受ImageUpload类型对象的重载?

先感谢您!!

我觉得你会遇到你提到的问题似乎很奇怪,所以我很好奇并使用你的服务合同整理了一个实现.那个实际上是直接工作的.我实际上并不知道你的情况出了什么问题(这不是很明显),但是让我在这里发布一个有效的解决方案,希望这能帮助你解决问题.

不幸的是,由于我多年前放弃了VB,我只能提供C#代码.希望没关系.

VB.NET中WCF服务使用TcpNetBinding时,为何StreamRequest无法接收数据流?

Server Web.config(在IIS中测试,使用net.tcp绑定):

<system.serviceModel> <bindings> <netTcpBinding> <binding transferMode="Streamed" maxReceivedMessageSize="1000000"> <security mode="None"/> </binding> </netTcpBinding> </bindings> <services> <service name="ImageSystem.SVC.UploadService"> <endpoint address="" binding="netTcpBinding" contract="ImageSystem.SVC.IUploadService"> </endpoint> <endpoint address="mex" kind="mexEndpoint" binding="mexTcpBinding"/> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata localhost/WcfService1/UploadService.svc" binding="netTcpBinding" contract="ImageServices.IUploadService" name="NetTcpBinding_IUploadService"> </endpoint> </client> </system.serviceModel>

服务合同&执行:

[ServiceContract(Namespace="urn:ImageSystem")] public interface IUploadService { [OperationContract] ImageUpload UploadFile(ImageUpload file); } [MessageContract] public class ImageUpload { [MessageHeader] public long? ImageID { get; set; } [MessageBodyMember] public Stream Data; } public class UploadService : IUploadService { public ImageUpload UploadFile(ImageUpload file) { long length; using (var ms = new MemoryStream()) { file.Data.CopyTo(ms); length = ms.Length; } return new ImageUpload { ImageID = length, Data = new MemoryStream() }; } }

测试应用:

private static readonly string imgPath = @"C:\Pictures\somepicture.jpg"; private static readonly EventWaitHandle waitHandle = new AutoResetEvent(false); static void Main() { long? result; using (var service = new ImageServices.UploadServiceClient("NetTcpBinding_IUploadService")) { var image = new ImageServices.ImageUpload(); using (var imgStream = File.OpenRead(imgPath)) { image.Data = imgStream; service.UploadFileCompleted += (sender, e) => { result = e.Result; if (e.Data != null) image.Data.Dispose(); waitHandle.Set(); }; service.UploadFileAsync(null, imgStream); waitHandle.WaitOne(); } } }

首先,正如您所看到的,配置文件可以更简单.特别是大型BufferSize值不是必需的.然后,关于服务合同,我不清楚为什么上传操作会收到AND返回一个ImageUpload消息.在我的实现中,我在ImageID参数中返回上传的文件大小,当然只是为了演示目的.我不知道你的合同背后的原因是什么,以及你真正想要回归的是什么.

实际上,当我知道你的代码为什么会失败时,就要点击“发送”.在测试客户端中,在调用serviceClient.UploadFileAsync()之前,将此行添加到代码中:ms.Seek(0,SeekOrigin.Begin).

这会将MemoryStream的位置重置回其开头.如果你不这样做,MemoryStream将仅从其当前位置消耗,这是它的结束 – 这解释了服务端收到的流的长度= 0!