2013-06-25 2 views
2

Я работаю над довольно прямолинейным распределенным приложением. Серверная часть предоставляет удаленный объект с именем 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, я уже проверил, что на пути нет брандмауэров и что сервер по-прежнему прослушивает правильный порт, когда это исключение выбрасывается из клиента.

+0

Это, вероятно, что-то вроде базового дескриптора сокета (это непрозрачный дескриптор), который повторно используется как «как есть», в то время как сокет фактически закрыт. Возможно, из-за чего-то статического в вашем коде, например, например, в топливном классе или в проблеме многопоточности. Трудно сказать без полного кода воспроизведения. –

+1

@ Grasshopper Если у вас есть небольшой полный пример, который реплицирует проблему, это было бы полезно. –

ответ

5

Я могу только дать вам подсказку, где искать проблему, вопрос не дает достаточно подробностей, чтобы сузить его. Сообщение об ошибке исключается из Windows и не связано с кодом .NET Framework. Или в этом случае ваш код. Копирование/вставка из WinError.ч заголовок файл SDK:

// 
// MessageId: WSAENOTSOCK 
// 
// MessageText: 
// 
// An operation was attempted on something that is not a socket. 
// 
#define WSAENOTSOCK      10038L 

Это экологическая ошибки, есть какое-то другое программное обеспечение связанно с разрушая ваш день. Интерпретация опасна, но грубая схема заключается в том, что создание сокета TCP, используемого для связи между машинами, а затем, почему-то, сокет закрыт или поврежден. Таким образом, сетевой драйвер низкого уровня больше не распознает его как подключенный сокет. Он подбрасывает руки и возвращает код ошибки 10038, «это не сокет!» .NET Framework превращает его в исключение, используя предварительно подготовленное сообщение об ошибке Windows.

Такая ошибка будет очень специфичной для машины или местоположения, на которых вы пытаетесь запустить свой код. У вас может быть лучшая удача с другой машиной. Не то, что вероятно, это, как правило, программное обеспечение, связанное с безопасностью, которое закручивает это. Там всегда много висит от конца сокета, в сети повсеместно используется вредоносное ПО, поэтому он может сражаться через уровни защиты. Узнайте больше о том, что работает на машине, и методы безопасности, используемые на сайте, имеют решающее значение для решения проблемы, обязательно поговорите с местным администратором локальной сети.

Есть другие сайты SE, где вы можете получить лучшую помощь, этот, вероятно, подходит для serverfault.com. Убедитесь, что вы можете документировать свой вопрос лучше, когда вы спрашиваете.

+0

Кто-нибудь думает, что это может быть вызвано ссылкой COM в классе обслуживания WCF? – Grasshopper

0

Решения, которые работают в среде разработки, могут не работать в процессе производства из-за различного экологического песочного бокса и безопасности. Поэтому давайте это выберем с тех пор, как вы уже охватили все.

Я не являюсь сокетом-гуру. Однако следуют некоторые из направлений, на которые я пойду;

a. Вам удалось вытащить журнал трассировки? (Вы можете сделать это с помощью msdn ref или stackoverflow ref.

b. Прежде чем совершать второй звонок, можете ли вы убедиться, что все используемые ручки первого вызова очищены/закрыты, когда они закончены? Это необходимо для того, чтобы ваш первый вызов был закрыт сокет правильно, прежде чем сделать вторую.

с. вы посылать пакеты данных, которые являются большими по размеру в пределах определенного времени. вы можете увеличить лимит времени в случае передачи больших объемов данных.

d. вы также может проверять наличие сбоев Socket на сервере с использованием msdn ref.

Позволяет проверить вышеупомянутое до дальнейшего обновления этой темы.