Question

I am working on a fairly straight-forward distributed application. The server portion exposes a remote object named FuelCommands that allows clients to interact with fuel pumps (i.e. authorize, deauthorize, reset, get status, etc...). The client is a windows form application that has a GUI for interacting with the pumps and viewing their status. Anytime the client needs to interact with the pumps, it must do so through the exposed remote object on the server. The issue is that the communication is not always successful on some Windows 8 machines. My development machine always works but, on other workstations running Windows 8, I get socket errors. Specifically, the error message is below:

************** 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)

Below, are some relevant code snippets that should demonstrate how the remote object is exposed and accessed. Can someone have a look and tell me why I might be getting this exception?

Server Application

// 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;
                }

In short, I'm confused for two reasons. First, I cannot understand why this works everytime on my development machine which is the same OS (Windows 8) as target machine. Secondly, I do not understand why the first call to remote object works and the second one fails. It is a different class accessing the remote object. The FuelPanel is basically a user control that sits on the main form. The PumpWidget (object that produces socket error) sits on FuelPanel. Can anyone possibly give me some tips? I know that the application should eventually move towards WCF but, we need to get it working for now.

BTW, I have already verified that there are no firewalls in the way and that the server is still listening on correct port when this exception is thrown from the client.

Was it helpful?

Solution

I can only give you a hint where to look for the problem, the question doesn't give enough details to narrow it down. The exception's error message comes straight out of Windows and is unrelated to the .NET Framework code. Or for that matter your code. Copy/pasted from the WinError.h SDK header file:

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

It is an environmental error, there's some kind of other software involved with ruining your day. Interpreting it is dangerous, but the rough outline is that creating the TCP socket that is used to communicate between the machines succeeded but then, somehow, the socket got closed or corrupted. So the low-level network driver doesn't recognize it as a connected socket anymore. It throws up it hands and returns error code 10038, "it is not a socket!" The .NET Framework turns it into an exception, using the pre-cooked Windows error message.

Such an error will be highly specific to the machine or location that you try to run your code on. You may have instant better luck with another machine. Not that likely, it tends to be security-related software that screws this up. There's always a lot of it hanging off the end of a socket, networking is routinely exploited by malware so it can be quite fight through layers of protection. Learning more about what is running on the machine and the security practices employed at the site is critical to solve the problem, be sure to talk to the local LAN administrator.

There are other SE sites where you can get better help, this one is probably a good fit for serverfault.com. Do make sure you can document your question better when you ask.

OTHER TIPS

Solutions which works in dev environment may not work in production due to various environmental sand-boxing and security. So let’s rule that out since you already covered all.

I am not a socket guru. However, following are some of the direction, which I shall go for;

a. Have you managed to pull the trace log? (You can do this using msdn ref or stackoverflow ref.

b. Before making the second call, can you ensure all of the used handles of first call is cleaned/closed when they are finished? This is to ensure your first call close the socket properly before making the second one.

c. Are you sending data packets that are large in size within the defined time. You may increase the time limit in case of large data transfers.

d. You can also check for Socket corruptions on server using msdn ref.

Lets check aforementioned before further update on this thread.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top