我正在开发一个相当简单的分布式应用程序。服务器部分公开了一个名为 FuelCommands 的远程对象,它允许客户端与燃料泵交互(即授权、取消授权、重置、获取状态等)。客户端是一个 Windows 窗体应用程序,具有用于与泵交互并查看其状态的 GUI。每当客户端需要与泵进行交互时,它必须通过服务器上暴露的远程对象来完成。问题是某些 Windows 8 机器上的通信并不总是成功的。我的开发机器总是可以工作,但是在其他运行 Windows 8 的工作站上,我得到了套接字错误。具体来说,错误消息如下:
************** Exception Text **************
System.Net.Sockets.SocketException: An operation was attempted on something that is not a socket
Server stack trace:
at System.Net.Sockets.Socket.Send(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Runtime.Remoting.Channels.SocketStream.Write(Byte[] buffer, Int32 offset, Int32 count)
at System.Runtime.Remoting.Channels.ChunkedMemoryStream.WriteTo(Stream stream)
at System.Runtime.Remoting.Channels.Tcp.TcpClientSocketHandler.GetRequestStream(IMessage msg, Int32 contentLength, ITransportHeaders headers)
at System.Runtime.Remoting.Channels.Tcp.TcpClientSocketHandler.SendRequest(IMessage msg, ITransportHeaders headers, Stream contentStream)
at System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.SendRequestWithRetry(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream)
at System.Runtime.Remoting.Channels.Tcp.TcpClientTransportSink.ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, Stream requestStream, ITransportHeaders& responseHeaders, Stream& responseStream)
at System.Runtime.Remoting.Channels.BinaryClientFormatterSink.SyncProcessMessage(IMessage msg)
下面是一些相关的代码片段,它们应该演示如何公开和访问远程对象。有人可以看看并告诉我为什么我可能会得到这个例外吗?
服务器应用程序
// Expose remote object
TcpChannel tcpChan = new TcpChannel(8090);
ChannelServices.RegisterChannel(tcpChan, false);
FuelCommands fuelcommands = new FuelCommands();
ObjRef o = RemotingServices.Marshal(fuelcommands, "objecturi");
客户
// Main form contains a fuel panel which contains a static reference to remote object
public static FDServer.FuelCommands fuelClass = null;
//Initialize the fuelClass object via the remote Fuel Server
//All code below is executed in Load event for this control which sits on main form for client
RemotingConfiguration.RegisterWellKnownClientType(Type.GetType("FDServer.FuelCommands, Fuel_Server"), "tcp://localhost:8090/objecturi");
fuelClass = new FuelCommands();
//fuelClass = (FDServer.FuelCommands)Activator.GetObject(typeof(FDServer.FuelCommands), GlobalSettings.FdProtocol + "://" + GlobalSettings.FdServerAddress + ":" + GlobalSettings.FdPortNum.ToString() + "/" + typeof(FDServer.FuelCommands).ToString());
//Test connection
fdServerConnGood = true;
// First use of remote object works without any issues
bool testConnection = fuelClass.aliveCheck();
// Client contains a bank of PumpWidget controls which are objects that encapsulate information about each pump
// This is where remote calls are failing with exception above
// The code below is executed from within a getStatus method every 2000ms fired by timer control
try
{
tempStatus = FuelPanel.fuelClass.get_FuelingPositionInformation(pumpNumberInt, 1); // FAILS with socket exception
}
catch (System.Net.Sockets.SocketException socketException)
{
logger.Error(socketException.Message);
throw;
}
简而言之,我感到困惑有两个原因。首先,我不明白为什么这在我的开发机器上每次都有效,它与目标机器是相同的操作系统(Windows 8)。其次,我不明白为什么第一次调用远程对象有效而第二次调用失败。它是访问远程对象的不同类。FuelPanel 基本上是位于主窗体上的用户控件。PumpWidget(产生套接字错误的对象)位于 FuelPanel 上。谁能给我一些提示?我知道应用程序最终应该转向 WCF,但是,我们现在需要让它工作。
顺便说一句,我已经验证了没有防火墙,并且当客户端抛出此异常时,服务器仍在侦听正确的端口。