Я работаю над довольно прямолинейным распределенным приложением. Серверная часть предоставляет удаленный объект с именем FuelCommands, который позволяет клиентам взаимодействовать с топливными насосами (то есть авторизировать, деавторизовать, перезагрузить, получить статус и т. Д.). Клиент представляет собой приложение для окон, которое имеет графический интерфейс для взаимодействия с насосами и просмотра их состояния. Каждый раз, когда клиент должен взаимодействовать с насосами, он должен делать это через открытый удаленный объект на сервере. Проблема в том, что связь не всегда успешна на некоторых машинах Windows 8. Моя машина разработки всегда работает, но на других рабочих станциях под управлением Windows 8 я получаю ошибки сокета. В частности, сообщение об ошибке ниже:Проблема сокета при попытке вызвать удаленный объект в C#
************** 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");
Client
// 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, но нам нужно заставить его работать сейчас.
BTW, я уже проверил, что на пути нет брандмауэров и что сервер по-прежнему прослушивает правильный порт, когда это исключение выбрасывается из клиента.
Это, вероятно, что-то вроде базового дескриптора сокета (это непрозрачный дескриптор), который повторно используется как «как есть», в то время как сокет фактически закрыт. Возможно, из-за чего-то статического в вашем коде, например, например, в топливном классе или в проблеме многопоточности. Трудно сказать без полного кода воспроизведения. –
@ Grasshopper Если у вас есть небольшой полный пример, который реплицирует проблему, это было бы полезно. –