在另一台计算机上作为 Windows 服务连接到 WCF 运行
Connecting to WCF running as a Windows Service on another computer
我有一个 WinForms 客户端应用程序。我在另一台计算机上有 WCF 服务器 运行 作为我编写的 Windows 服务的一部分。我第一次尝试 NetPipeBinding
,现在 NetTcpBinding
。我确实在 Windows 高级安全防火墙 中打开了 2 个端口。服务器 OS 是 Windows 服务器 2016.
这是服务器代码:
public Boolean CreatePipeServer(out string logEntry)
{
try
{
NetTcpBinding ipcBinding = new NetTcpBinding()
{
Security = new NetTcpSecurity()
{
Mode = SecurityMode.None,
Transport = new TcpTransportSecurity()
{
ClientCredentialType = TcpClientCredentialType.None,
ProtectionLevel = System.Net.Security.ProtectionLevel.None,
},
},
MaxBufferPoolSize = 6553600,
MaxBufferSize = 6553600,
MaxReceivedMessageSize = 6553600,
MaxConnections = 1000,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxNameTableCharCount = 2147483647,
MaxStringContentLength = 2147483647,
},
};
// Instantiate: Host Service
Uri uriMex = new Uri("http://localhost:8000");
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService = new ServiceHost(typeof(IpcAppToService), uriMex);
// Instantiate: Endpoint
Uri uriService = new Uri("net.tcp://localhost:8004/StampIpcAppToService");
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.AddServiceEndpoint(typeof(StampIpc.IIpcAppToService), ipcBinding, uriService);
// Instantiate: Service Meta Behavior
ServiceMetadataBehavior ipcSmb = this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (null == ipcSmb)
{
ipcSmb = new ServiceMetadataBehavior()
{
HttpGetEnabled = true,
};
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description.Behaviors.Add(ipcSmb);
ServiceDescription serviceDescription = this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description;
}
// Instantiate: MEX Biding
Binding ipcMexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.AddServiceEndpoint(typeof(IMetadataExchange), ipcMexBinding, "MEX");
// Capture events.
...
// Start the service.
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Open();
return true;
}
catch (Exception) { }
return false;
}
我正在尝试通过转到 Visual Studio 2019
中的 Add > Service Reference...
来测试有效的通信 link。无论我输入什么,我都会不断收到这样或那样的错误。目前,我放置:
net.tcp://10.10.70.134:8004/StampIpcAppToService
抛出错误:
The URI prefix is not recognized.
Metadata contains a reference that cannot be resolved: 'net.tcp://10.10.70.134:8004/StampIpcAppToService'.
Metadata contains a reference that cannot be resolved: 'net.tcp://10.10.70.134:8004/StampIpcAppToService'.
If the service is defined in the current solution, try building the solution and adding the service reference again.
我已经有了客户端代码,但是如果我不能让Add Service Reference
工作,那么客户端代码肯定是行不通的。
上面的代码作为 Windows Service
的 OnStart
事件的一部分开始。
我做错了什么?
更新
答案解决了上面的直接问题,但是我的真实代码使用类似于服务器端的代码,我收到错误。我根据答案和一些调试修改了代码。当前代码是:
public static Boolean ConnectToService()
{
ComAppToService.IsPipeAppToService = false;
ComAppToService.IpcPipeFactory = null;
Program.HostIpcAppToService = null;
try
{
// Instantiate: Callack
var ipcCallback = new IpcAppToServiceBack();
InstanceContext ipcCallbackInstance = new InstanceContext(ipcCallback);
// Instantiate: Endpoint
Uri ipcUri = new Uri($"http://10.10.70.134:8000/mex");
EndpointAddress ipcEndpoint = new EndpointAddress(ipcUri);
// Instantiate: Binding
//
WSDualHttpBinding ipcBindingHttp = new WSDualHttpBinding()
{
Security = new WSDualHttpSecurity() { Mode = WSDualHttpSecurityMode.None },
MaxBufferPoolSize = 6553600,
MaxReceivedMessageSize = 6553600,
ClientBaseAddress = ipcUri,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxNameTableCharCount = 2147483647,
MaxStringContentLength = 2147483647,
},
};
// Instantiate: Factory
ComAppToService.IpcPipeFactory = new DuplexChannelFactory<IIpcAppToService>(ipcCallbackInstance, ipcBindingHttp, ipcEndpoint);
Program.HostIpcAppToService = ComAppToService.IpcPipeFactory.CreateChannel();
// Open: Callback
Program.HostIpcAppToService.OpenCallback(IpcCallbackDest.App);
ComAppToService.IsPipeAppToService = true;
return true;
}
catch (Exception ex)
{
// Log the exception.
Debug.WriteLine(ex.Message);
}
return false;
}
异常:
InnerException = {"The message with Action
'http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence' cannot be
processed at the receiver, due to a ContractFilter mismatch at the
EndpointDispatcher. This may be because of either a contract mismatch
(mismatched Actions betwee...
更新 2(反映更新的答案)
使用 NetTcpBinding
生成此错误:
使用 URI:
Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8004");
生成
Message = "There was no endpoint listening at net.tcp://jmr-engineering:8004/ that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."
使用 URI:
Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8000");
生成
Message = "You have tried to create a channel to a service that does not support .Net Framing. It is possible that you are encountering an HTTP endpoint."
InnerException = {"Expected record type 'PreambleAck', found '72'."}
答案:
接受的答案需要修改。亚伯拉罕没有正确的 URI
,但他指给我 SvcUtil.exe
,后者给了我。
URI:
net.tcp://10.10.70.134:8004/StampIpcAppToService
我确实需要NetTcpBinding
,所以最终的客户端代码是:
/// <summary>
/// Connects the ipc application to service.
/// </summary>
/// <returns>Boolean.</returns>
public static Boolean ConnectToService()
{
ComAppToService.IsPipeAppToService = false;
ComAppToService.IpcPipeFactory = null;
Program.HostIpcAppToService = null;
try
{
// Instantiate: Callack
var ipcCallback = new IpcAppToServiceBack();
InstanceContext ipcCallbackInstance = new InstanceContext(ipcCallback);
// Instantiate: Endpoint
Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8004/StampIpcAppToService");
EndpointAddress ipcEndpoint = new EndpointAddress(ipcUri);
// Instantiate: Binding
//
NetTcpBinding ipcBindingHttp = new NetTcpBinding()
{
Security = new NetTcpSecurity() { Mode = SecurityMode.None },
MaxBufferPoolSize = 6553600,
MaxReceivedMessageSize = 6553600,
MaxBufferSize = 6553600,
MaxConnections = 1000,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxNameTableCharCount = 2147483647,
MaxStringContentLength = 2147483647,
},
};
// Instantiate: Factory
ComAppToService.IpcPipeFactory = new DuplexChannelFactory<IIpcAppToService>(ipcCallbackInstance, ipcBindingHttp, ipcEndpoint);
Program.HostIpcAppToService = ComAppToService.IpcPipeFactory.CreateChannel();
// Open: Callback
Program.HostIpcAppToService.OpenCallback(IpcCallbackDest.App);
ComAppToService.IsPipeAppToService = true;
return true;
}
catch (Exception ex)
{
// Log the exception.
Debug.WriteLine(ex.Message);
}
return false;
}
这是 output.config
从 SvcUtil.exe
的输出。 IpcAppToService.cs
文件没用,但配置文件绝对有用。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IIpcAppToService">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:8004/StampIpcAppToService"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IIpcAppToService"
contract="IIpcAppToService" name="NetTcpBinding_IIpcAppToService" />
</client>
</system.serviceModel>
</configuration>
添加服务引用依赖于服务元数据地址,而不是服务地址。根据您的上述设置,您添加服务引用对话框中的 Uri 应该是,
通常,我们必须通过添加 Mex
端点或 ServiceMetedataBehavior
的 HttpGetEnabled
属性 来公开元数据。随后,客户端可以使用SVCUtil
工具生成客户端代理。
https://docs.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
在Visual Studio
中,Adding Service reference
对话框是生成客户端代理的快捷方式。它依赖于 Mex
服务端点。 Mex
端点地址是快捷方式所必需的。
如果有什么我可以帮忙的,请随时告诉我。
已更新。
双工通信意味着我们应该在客户端使用Nettcpbinding
(支持双工)。
class Program
{
static void Main(string[] args)
{
NetTcpBinding binding = new NetTcpBinding()
{
Security = new NetTcpSecurity
{
Mode = SecurityMode.None
},
MaxBufferPoolSize = 6553600,
MaxBufferSize = 6553600,
MaxReceivedMessageSize = 6553600,
MaxConnections = 1000,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxNameTableCharCount = 2147483647,
MaxStringContentLength = 2147483647,
},
};
//replace it with your practical service address.
Uri uri = new Uri("net.tcp://10.157.13.69:8004");
ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
IService service = factory.CreateChannel();
var result = service.Test();
Console.WriteLine(result);
}
}
//the service contract shared between the client-side and the server-side.
[ServiceContract]
public interface IService
{
[OperationContract]
string Test();
}
我有一个 WinForms 客户端应用程序。我在另一台计算机上有 WCF 服务器 运行 作为我编写的 Windows 服务的一部分。我第一次尝试 NetPipeBinding
,现在 NetTcpBinding
。我确实在 Windows 高级安全防火墙 中打开了 2 个端口。服务器 OS 是 Windows 服务器 2016.
这是服务器代码:
public Boolean CreatePipeServer(out string logEntry)
{
try
{
NetTcpBinding ipcBinding = new NetTcpBinding()
{
Security = new NetTcpSecurity()
{
Mode = SecurityMode.None,
Transport = new TcpTransportSecurity()
{
ClientCredentialType = TcpClientCredentialType.None,
ProtectionLevel = System.Net.Security.ProtectionLevel.None,
},
},
MaxBufferPoolSize = 6553600,
MaxBufferSize = 6553600,
MaxReceivedMessageSize = 6553600,
MaxConnections = 1000,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxNameTableCharCount = 2147483647,
MaxStringContentLength = 2147483647,
},
};
// Instantiate: Host Service
Uri uriMex = new Uri("http://localhost:8000");
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService = new ServiceHost(typeof(IpcAppToService), uriMex);
// Instantiate: Endpoint
Uri uriService = new Uri("net.tcp://localhost:8004/StampIpcAppToService");
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.AddServiceEndpoint(typeof(StampIpc.IIpcAppToService), ipcBinding, uriService);
// Instantiate: Service Meta Behavior
ServiceMetadataBehavior ipcSmb = this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (null == ipcSmb)
{
ipcSmb = new ServiceMetadataBehavior()
{
HttpGetEnabled = true,
};
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description.Behaviors.Add(ipcSmb);
ServiceDescription serviceDescription = this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Description;
}
// Instantiate: MEX Biding
Binding ipcMexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.AddServiceEndpoint(typeof(IMetadataExchange), ipcMexBinding, "MEX");
// Capture events.
...
// Start the service.
this.ServiceParent.ServiceIpcAppToService.HostIpcAppToService.Open();
return true;
}
catch (Exception) { }
return false;
}
我正在尝试通过转到 Visual Studio 2019
中的 Add > Service Reference...
来测试有效的通信 link。无论我输入什么,我都会不断收到这样或那样的错误。目前,我放置:
net.tcp://10.10.70.134:8004/StampIpcAppToService
抛出错误:
The URI prefix is not recognized. Metadata contains a reference that cannot be resolved: 'net.tcp://10.10.70.134:8004/StampIpcAppToService'. Metadata contains a reference that cannot be resolved: 'net.tcp://10.10.70.134:8004/StampIpcAppToService'. If the service is defined in the current solution, try building the solution and adding the service reference again.
我已经有了客户端代码,但是如果我不能让Add Service Reference
工作,那么客户端代码肯定是行不通的。
上面的代码作为 Windows Service
的 OnStart
事件的一部分开始。
我做错了什么?
更新
答案解决了上面的直接问题,但是我的真实代码使用类似于服务器端的代码,我收到错误。我根据答案和一些调试修改了代码。当前代码是:
public static Boolean ConnectToService()
{
ComAppToService.IsPipeAppToService = false;
ComAppToService.IpcPipeFactory = null;
Program.HostIpcAppToService = null;
try
{
// Instantiate: Callack
var ipcCallback = new IpcAppToServiceBack();
InstanceContext ipcCallbackInstance = new InstanceContext(ipcCallback);
// Instantiate: Endpoint
Uri ipcUri = new Uri($"http://10.10.70.134:8000/mex");
EndpointAddress ipcEndpoint = new EndpointAddress(ipcUri);
// Instantiate: Binding
//
WSDualHttpBinding ipcBindingHttp = new WSDualHttpBinding()
{
Security = new WSDualHttpSecurity() { Mode = WSDualHttpSecurityMode.None },
MaxBufferPoolSize = 6553600,
MaxReceivedMessageSize = 6553600,
ClientBaseAddress = ipcUri,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxNameTableCharCount = 2147483647,
MaxStringContentLength = 2147483647,
},
};
// Instantiate: Factory
ComAppToService.IpcPipeFactory = new DuplexChannelFactory<IIpcAppToService>(ipcCallbackInstance, ipcBindingHttp, ipcEndpoint);
Program.HostIpcAppToService = ComAppToService.IpcPipeFactory.CreateChannel();
// Open: Callback
Program.HostIpcAppToService.OpenCallback(IpcCallbackDest.App);
ComAppToService.IsPipeAppToService = true;
return true;
}
catch (Exception ex)
{
// Log the exception.
Debug.WriteLine(ex.Message);
}
return false;
}
异常:
InnerException = {"The message with Action 'http://schemas.xmlsoap.org/ws/2005/02/rm/CreateSequence' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions betwee...
更新 2(反映更新的答案)
使用 NetTcpBinding
生成此错误:
使用 URI:
Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8004");
生成
Message = "There was no endpoint listening at net.tcp://jmr-engineering:8004/ that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details."
使用 URI:
Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8000");
生成
Message = "You have tried to create a channel to a service that does not support .Net Framing. It is possible that you are encountering an HTTP endpoint."
InnerException = {"Expected record type 'PreambleAck', found '72'."}
答案:
接受的答案需要修改。亚伯拉罕没有正确的 URI
,但他指给我 SvcUtil.exe
,后者给了我。
URI:
net.tcp://10.10.70.134:8004/StampIpcAppToService
我确实需要NetTcpBinding
,所以最终的客户端代码是:
/// <summary>
/// Connects the ipc application to service.
/// </summary>
/// <returns>Boolean.</returns>
public static Boolean ConnectToService()
{
ComAppToService.IsPipeAppToService = false;
ComAppToService.IpcPipeFactory = null;
Program.HostIpcAppToService = null;
try
{
// Instantiate: Callack
var ipcCallback = new IpcAppToServiceBack();
InstanceContext ipcCallbackInstance = new InstanceContext(ipcCallback);
// Instantiate: Endpoint
Uri ipcUri = new Uri($"net.tcp://10.10.70.134:8004/StampIpcAppToService");
EndpointAddress ipcEndpoint = new EndpointAddress(ipcUri);
// Instantiate: Binding
//
NetTcpBinding ipcBindingHttp = new NetTcpBinding()
{
Security = new NetTcpSecurity() { Mode = SecurityMode.None },
MaxBufferPoolSize = 6553600,
MaxReceivedMessageSize = 6553600,
MaxBufferSize = 6553600,
MaxConnections = 1000,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxNameTableCharCount = 2147483647,
MaxStringContentLength = 2147483647,
},
};
// Instantiate: Factory
ComAppToService.IpcPipeFactory = new DuplexChannelFactory<IIpcAppToService>(ipcCallbackInstance, ipcBindingHttp, ipcEndpoint);
Program.HostIpcAppToService = ComAppToService.IpcPipeFactory.CreateChannel();
// Open: Callback
Program.HostIpcAppToService.OpenCallback(IpcCallbackDest.App);
ComAppToService.IsPipeAppToService = true;
return true;
}
catch (Exception ex)
{
// Log the exception.
Debug.WriteLine(ex.Message);
}
return false;
}
这是 output.config
从 SvcUtil.exe
的输出。 IpcAppToService.cs
文件没用,但配置文件绝对有用。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding_IIpcAppToService">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:8004/StampIpcAppToService"
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IIpcAppToService"
contract="IIpcAppToService" name="NetTcpBinding_IIpcAppToService" />
</client>
</system.serviceModel>
</configuration>
添加服务引用依赖于服务元数据地址,而不是服务地址。根据您的上述设置,您添加服务引用对话框中的 Uri 应该是,
通常,我们必须通过添加 Mex
端点或 ServiceMetedataBehavior
的 HttpGetEnabled
属性 来公开元数据。随后,客户端可以使用SVCUtil
工具生成客户端代理。
https://docs.microsoft.com/en-us/dotnet/framework/wcf/accessing-services-using-a-wcf-client
在Visual Studio
中,Adding Service reference
对话框是生成客户端代理的快捷方式。它依赖于 Mex
服务端点。 Mex
端点地址是快捷方式所必需的。
如果有什么我可以帮忙的,请随时告诉我。
已更新。
双工通信意味着我们应该在客户端使用Nettcpbinding
(支持双工)。
class Program
{
static void Main(string[] args)
{
NetTcpBinding binding = new NetTcpBinding()
{
Security = new NetTcpSecurity
{
Mode = SecurityMode.None
},
MaxBufferPoolSize = 6553600,
MaxBufferSize = 6553600,
MaxReceivedMessageSize = 6553600,
MaxConnections = 1000,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = 2147483647,
MaxBytesPerRead = 2147483647,
MaxDepth = 2147483647,
MaxNameTableCharCount = 2147483647,
MaxStringContentLength = 2147483647,
},
};
//replace it with your practical service address.
Uri uri = new Uri("net.tcp://10.157.13.69:8004");
ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
IService service = factory.CreateChannel();
var result = service.Test();
Console.WriteLine(result);
}
}
//the service contract shared between the client-side and the server-side.
[ServiceContract]
public interface IService
{
[OperationContract]
string Test();
}