2013-06-25 32 views
2

我正在研究一個相當直接的分佈式應用程序。服務器部分暴露名爲FuelCommands的遠程對象,該對象允許客戶端與燃油泵進行交互(即授權,取消授權,重置,獲取狀態等)。客戶端是一個Windows窗體應用程序,它具有與泵交互並查看其狀態的GUI。客戶端需要與泵進行交互時,必須通過服務器上暴露的遠程對象執行此操作。問題在於,某些Windows 8計算機上的通信並不總是成功。我的開發機器總能正常工作,但在運行Windows 8的其他工作站上,我遇到套接字錯誤。具體而言,錯誤消息下面是:嘗試調用C#中的遠程對象時出現Socket問題#

************** 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,但是,我們需要現在就開始工作。

順便說一句,我已經證實,沒有防火牆的方式,並且當客戶端拋出此異常時,服務器仍在偵聽正確的端口。

+0

它可能是一個底層的套接字描述符(它是一個不透明的句柄),當套接字實際上已關閉時,它被重用「原樣」。也許是由於你的代碼中存在靜態的東西,比如fuelClass,或者/和一個多線程問題。沒有完整的複製代碼很難說。 –

+1

@Grasshopper如果你有一個複製問題的小完整例子,這將會有所幫助。 –

回答

5

我只能給你一個提示在哪裏尋找問題,這個問題沒有給出足夠的細節來縮小它。異常的錯誤消息直接來自Windows,與.NET Framework代碼無關。或者你的代碼。從WinError複製/粘貼。^ h 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

有沒有人認爲這可能是由WCF服務類中的COM引用造成的? – Grasshopper

0

在開發環境中工作的解決方案由於各種環境沙盒和安全性可能無法在生產環境中工作。所以讓我們先來解釋一下,因爲你已經涵蓋了所有的內容

我不是套接字大師。但是,下面是我要去的一些方向,

a。你有沒有設法拉出跟蹤日誌? (您可以使用msdn refstackoverflow ref做到這一點。

灣進行第二個呼叫之前,可以確保所有的第一個電話的使用手柄進行清潔/他們時完成關閉?這是爲了保證你的第一個調用close插槽正確之前做第二個。

角你發送是在規定的時間內,大小大的數據包,你可能會增加時間限制的大量數據的傳輸情況。

d。您還可以使用msdn ref檢查服務器上的套接字損壞情況。

讓我們在此線程進一步更新之前進行檢查。

相關問題