gpt4 book ai didi

vb.net - WCF 服务 TcpNetBinding StreamRequest 未接收流

转载 作者:行者123 更新时间:2023-12-01 04:11:34 24 4
gpt4 key购买 nike

我的第一个问题,所以要温柔=)

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

服务契约(Contract)如下:

<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

相关的服务器配置/绑定(bind)如下(这些显然只是开发环境设置):
<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 httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

WCF 服务是一个服务库,由 Web 应用程序托管。 Web 应用程序项目在我的本地 IIS 7.5 中运行。 IIS 已配置为启用 TCP 连接,并为应用程序池标识配置了合约实现的相关权限。 VS2010 以管理员身份运行以在 IIS 中启用调试。

为了测试契约(Contract)实现,我将 Windows 控制台应用程序设置为(测试)客户端。客户端代理类是通过在 IIS 主机 (http://localhost/ImageSystem/UploadService.svc) 中添加对服务的服务引用来生成的。服务引用被配置为生成异步方法。

相关的自动生成的客户端配置如下(注意,我尝试增加 maxBufferPoolSize、maxBufferSize 和 maxReceivedMessageSize 以匹配“20971520”的服务器配置,但无济于事):

[编辑:根据 Sixto Saez 的建议,reliableSessions 部分已注释掉,但无济于事]
<system.serviceModel>

<bindings>
<binding name="NetTcpBinding_IUploadService" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Streamed" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="20971520"
maxBufferSize="20971520" maxConnections="10" maxReceivedMessageSize="20971520">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<!--<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />-->
<security mode="None">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
</bindings>

<client>
<endpoint address="net.tcp://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 字节(应在相关请求/缓冲区最大大小范围内)。

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

方法一:
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

方法二:
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 类型对象的重载?

先感谢您!!

最佳答案

你会遇到你提到的问题对我来说似乎很奇怪,所以我很好奇并使用你的服务契约(Contract)组合了一个实现。那一个实际上立即起作用了。我实际上不知道您的情况出了什么问题(这并不明显),但是让我在这里发布一个可行的解决方案,希望这可以帮助您解决问题。

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

服务器 Web.config(在 IIS 中测试,使用 net.tcp 绑定(bind)):

  <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 httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>

客户端 app.config(控制台测试应用):
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding transferMode="Streamed" maxReceivedMessageSize="1000000">
<security mode="None"/>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint
address="net.tcp://localhost/WcfService1/UploadService.svc"
binding="netTcpBinding"
contract="ImageServices.IUploadService"
name="NetTcpBinding_IUploadService">
</endpoint>
</client>
</system.serviceModel>

服务契约(Contract)及执行:
[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值不是必需的。然后,关于服务契约(Contract),我不清楚为什么 Upload操作将接收并返回 ImageUpload信息。在我的实现中,我在 ImageID 中返回上传的文件大小。当然,参数仅用于演示目的。我不知道您签订该契约(Contract)的原因是什么,以及您实际上想要返回什么。

实际上,当我知道您的代码可能失败的原因时,我正要单击“发送”。在您的测试客户端中,在您调用 serviceClient.UploadFileAsync() 之前,将此行添加到您的代码中: ms.Seek(0, SeekOrigin.Begin) .

这会将 MemoryStream 的位置重置回其开头。如果您不这样做,则 MemoryStream 将仅从其当前位置(即其末端)消耗 - 这解释了在服务端接收到的流的 Length = 0!

关于vb.net - WCF 服务 TcpNetBinding StreamRequest 未接收流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5790675/

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