简体   繁体   中英

C# Socket.Receive() SocketException: A request to send or receive data was disallowed because the socket is not connected

I'm struggling with Windows Socket programming in C#, .Net 4.5 on Windows 8.1.

So, I'm doing a pretty simple operation. I'm implementing a client-server type system all to be run on a the local machine, communicating over sockets. The server is a Windows Service, the client is a user application.

The service, upon request from the client, performs some OCR computation then returns the results to the requesting process. The service has a listening socket that accepts incoming requests at all times, a new socket is created and used to respond to each requests. The port # for the new responding socket is specified in the request. This is done to allow the listening socket to handle concurrent requests.

The service's listening socket is working fine. I am able to receive requests from a user application connected to the listening socket. The problem occurs when the roles are reversed: the service needs to connect to the Socket owned by the client and send the OCR results over the client-owned socket. Let's get into the code:

Server Side

this.LocalAddress = Dns.GetHostEntry("localhost").AddressList[0]; // localhost ip addr

...
//*************** Receive request
//*************** Perform computation
...

// respond to requester with results from OCR 
using (Socket responder = new Socket(this.LocalAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
    IPEndPoint requestEndpoint = new IPEndPoint(this.LocalAddress, request.portNum);
    responder.Connect(requestEndpoint); //same endpoint as client

    if(failure)
        responder.Send(Encoding.UTF8.GetBytes(this.OCRFailureMessage));
    else
        responder.Send(Encoding.UTF8.GetBytes(ocrResults.ToString()));
}

No exceptions are thrown, service continues as if everything happened successfully.

Client Side

//localhost address
IPAddress address = Dns.GetHostEntry("localhost").AddressList[0]; // localhost ip addr

// endpoint to listen on for response from StartOCRService
IPEndPoint myEndpoint = new IPEndPoint(address, 50002);

// create socket to receive response on and bind to listening endpoint
Socket receiver = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
receiver.Bind(myEndpoint);
receiver.Listen(10);

...
//************ Connect to service listening socket
//************ Send OCR request to service (myEndpoint port# included)
...

// accept connection from service
receiver.Accept();

// receive data from service
byte[] returnData = new byte[1024];
int numBytesReceived = receiver.Receive(returnData); //EXCEPTION THROWN

The exception is thrown in the client side on the receiver.Receive() call. Here are the exception details:

Type: SocketException

Message: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied.

ErrorCode: 10057 (Socket is not connected)

So, where I'm hung up is how the client's socket is not connected. The line receiver.Accept() is a blocking call that waits for the server to call responder.Connect() . Stepping through both sides concurrently I see the client wait on receiver.Accept() until the server calls responder.Connect() . I take this to mean that the client socket has accepted a connection. Can anybody spot the reason why the client's socket is remaining unconnected and this exception is being thrown?

All help is greatly appreciated, thanks SO!

EDIT: 7/29/2015 5:07p

Some additional details that may be helpful. After the service calls responder.Connect() responder.Connected is true and responder.RemoteEndpoint is the endpoint that the client is listening on (address and port# confirmed).

The same cannot be said for the client however. After the receiver.Accept() call passes receiver.Connected is false and receiver.RemoteEndpoint threw the same exception as above.

Digging further into receiver's members I found receiver.DontFragment threw a System.NotSupportedException with the message

This protocol version is not supported.

Something wrong with the protocol I'm using? I'm using TCP across the board. Perhaps it has something to do with the address families?

A TCP server listening socket is used for accepting connections, it is NOT used for subsequent data exchanges with TCP client peers. accept() returns another, unique client<>server socket for each peer client that connects.

A very common pattern is for one server to supply a request/response service to many clients. A client<>server socket returned by accept() can be communicated to a thread or process, dedicated to that client, that reads, parses, handles its client requests and sends replies on the same client<>server socket. Alternatively, a select/epoll asynchronous design can handle the request/response in one thread/process.

One thread/process per client requires a stack for each client, (bad), but allows simple 'in-line' code, (good).

Asynchronous select/epoll needs only one stack, (good), but usually requires a user space state-machine to handle the events, (bad).

Pick your poison:)

It is much more uncommon to close the client<>server socket after a request has come in and then, later, to try and open a connection in the other direction to provide the reply. That requires a server and client at both peers and gets very messy.

So @Martin James has helped me tremendously with my design flaws. There is no reason to establish a new socket connection after the request has been made over a existing socket connection. The exception being thrown was beside the design, however bad it may have been. This line accepting a connection in my client side code

// accept connection from service
receiver.Accept();

needed to be

// accept connection from service
Socket handler = receiver.Accept();

and then use handler to receive messages. The returned socket object is correctly connected.

Thanks again @Martin James

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM