我是这个 WCF 的新手,我需要让涉及 WCF 的项目开始工作。因此,我通过使用 NetTcpBinding 硬编码 IP 地址来创建一个非常简单的 wcf 来测试水以简化配置,但我无法让它工作。请看一下,看看是否有什么让你兴奋的地方,如果你能指出我做错了什么,我将不胜感激。我有一个 WCFLib、WCFHost 和 WCFClient。如果一切都在同一台机器上,那就很好了,而且客户端和主机运行良好,结果是正确的。但是,如果主机在一台机器上,而客户端在同一子网中的另一台机器上,没有防火墙(客户端可以成功 ping 主机)并且我尝试运行客户端然后单击应用程序中的“=”按钮,我得到这个错误:
See the end of this message for details on invoking
just-in-time (JIT) debugging instead of this dialog box.
************** Exception Text **************
System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.
Server stack trace:
at System.ServiceModel.Channels.CommunicationObject.ThrowIfDisposedOrNotOpen()
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at WCFLib.ICalculator.Add(Int32 arg1, Int32 arg2)
at WCFClient.CalculatorClient.bResult_Click(Object sender, EventArgs e) in c:\Frank\Testing\WCFClient\CalculatorClient.cs:line 37
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
************** Loaded Assemblies **************
mscorlib
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.18033 built by: FX45RTMGDR
CodeBase: file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/mscorlib.dll
----------------------------------------
WCFClient
Assembly Version: 1.0.0.0
Win32 Version: 1.0.0.0
CodeBase: file:///C:/xxx/WCFClient/bin/Debug/WCFClient.exe
----------------------------------------
System.Windows.Forms
Assembly Version: 4.0.0.0
Win32 Version: 4.0.30319.18037 built by: FX45RTMGDR
CodeBase: file:///C:/Windows/Microsoft.Net/assembly/GAC_MSIL/System.Windows.Forms/v4.0_4.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System.Drawing
Assembly Version: 4.0.0.0
以下是我的 WCFClient、WCFHost 和 WCFLib 代码: 当主机和客户端在同一台机器上时,代码编译并运行成功。仅当它们位于同一子网上的不同机器上时才会发生错误,其中一台机器可以 ping 另一台机器。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using WCFLib;
namespace WCFHost
{
class Program
{
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(Calculator));
host.AddServiceEndpoint(typeof(ICalculator), new NetTcpBinding(), "net.tcp://xxx.xxx.xxx.xxx:9000");
host.Open();
Console.ReadLine();
host.Close();
}
}
}
--------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WCFLib
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract(Namespace = "http://www.mywebsite.com/WCFLib")]
public interface ICalculator
{
[OperationContract(Name="AddInt")]
int Add(int arg1, int arg2);
[OperationContract(Name = "AddDouble")]
Double Add(Double arg1, Double arg2);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
// TODO: Add your service operations here
}
// Use a data contract as illustrated in the sample below to add composite types to service operations.
// You can add XSD files into the project. After building the project, you can directly use the data types defined there, with the namespace "WCFLib.ContractType".
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
}
----------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
namespace WCFLib
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
public class Calculator : ICalculator
{
public int Add(int arg1, int arg2)
{
return arg1+arg2;
}
public Double Add(Double arg1, Double arg2)
{
return arg1 + arg2;
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException("composite");
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
}
-------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ServiceModel;
using WCFLib;
namespace WCFClient
{
public partial class CalculatorClient : Form
{
public ICalculator proxy;
public CalculatorClient()
{
InitializeComponent();
ChannelFactory<ICalculator> ch;
ch = new ChannelFactory<ICalculator>(new NetTcpBinding(), "net.tcp://xxx.xxx.xxx.xxx:9000");
proxy = ch.CreateChannel();
}
private void bAdd_Click(object sender, EventArgs e)
{
}
private void bResult_Click(object sender, EventArgs e)
{
tboxResult.Text=proxy.Add(12, 45).ToString();
}
}
}