简体   繁体   English

C#Socket.Receive()SocketException:因为未连接套接字,所以不允许发送或接收数据的请求

[英]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. 我正在Windows 8.1的C#、. Net 4.5中的Windows套接字编程方面苦苦挣扎。

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. 服务器是Windows服务,客户端是用户应用程序。

The service, upon request from the client, performs some OCR computation then returns the results to the requesting process. 该服务根据客户的请求执行一些OCR计算,然后将结果返回给请求过程。 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. 当角色互换时会发生问题:服务需要连接到客户端拥有的套接字,并通过客户端拥有的套接字发送OCR结果。 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. 异常在客户端上通过receiver.Receive()调用引发。 Here are the exception details: 以下是异常详细信息:

Type: SocketException 类型: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. 消息:不允许发送或接收数据的请求,因为未连接套接字,并且(当使用sendto调用在数据报套接字上发送时)未提供地址。

ErrorCode: 10057 (Socket is not connected) 错误代码:10057(未连接套接字)

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() . 线路receiver.Accept()是一个阻塞调用,它等待服务器调用responder.Connect() Stepping through both sides concurrently I see the client wait on receiver.Accept() until the server calls responder.Connect() . 同时执行两个步骤,我看到客户端在等待receiver.Accept()直到服务器调用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 编辑: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). 服务调用后, responder.Connect() responseer.Connected为true ,responder.RemoteEndpoint是客户端正在侦听的端点(已确认地址和端口号)。

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. receiver.Accept()调用传递到receive.Connected之后为false,并且receive.RemoteEndpoint引发与上述相同的异常。

Digging further into receiver's members I found receiver.DontFragment threw a System.NotSupportedException with the message 进一步研究接收者的成员,我发现了接收器。DontFragment抛出了System.NotSupportedException与消息

This protocol version is not supported. 不支持该协议版本。

Something wrong with the protocol I'm using? 我使用的协议有问题吗? I'm using TCP across the board. 我正在全面使用TCP。 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. TCP服务器侦听套接字用于接受连接,而不用于与TCP客户端对等方的后续数据交换。 accept() returns another, unique client<>server socket for each peer client that connects. accept()为每个连接的对等客户端返回另一个唯一的client <> server套接字。

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. 可以将accept()返回的client <> server套接字与该客户端专用的线程或进程进行通信,该线程或进程在同一client <> server套接字上读取,解析,处理其客户端请求并发送答复。 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. 在请求进入后关闭client <>服务器套接字,然后稍后尝试在另一个方向上打开连接以提供答复的情况,这种情况更为罕见。 That requires a server and client at both peers and gets very messy. 这需要在两个对等服务器和客户端,并且变得非常混乱。

So @Martin James has helped me tremendously with my design flaws. 因此,@ Martin James为我的设计缺陷提供了极大帮助。 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. 然后使用handler来接收消息。 The returned socket object is correctly connected. 返回的套接字对象已正确连接。

Thanks again @Martin James 再次感谢@Martin James

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 由于套接字未连接C#,因此不允许发送或接收数据的请求 - A request to send or receive data was disallowed because the socket is not connected C# C# 发送或接收数据的请求被禁止,因为套接字未连接 - C# A request to send or receive data was disallowed because the socket is not connected 由于未连接套接字,因此不允许发送或接收数据的请求。 。 - A request to send or receive data was disallowed because the socket is not connected . . 不允许发送或接收数据的请求,因为未连接套接字且未提供地址 - A request to send or receive data was disallowed because the socket is not connected and no address was supplied 套接字未连接,不允许发送或接收数据的请求 - A request to send or receive data was disallowed the socket is not connected 由于套接字未连接-发送数据时,不允许发送或接收数据的请求 - A request to send or receive data was disallowed because the socket is not connected - when sending data 由于未连接套接字,因此不允许发送或接收数据的请求(仅当我第二次连接时) - A request to send or receive data was disallowed because the socket is not connected (only if I connect 2nd time) C#Socket.Receive消息长度 - C# Socket.Receive message length 调用Socket.Receive后,C#Socket.Connected属性更改为false - C# Socket.Connected property is changed to false after calling Socket.Receive C#TCP Socket.Reuse复用套接字时出现问题 - C# TCP Socket.Receive issue when reusing socket
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM