【发布时间】:2015-07-29 22:55:41
【问题描述】:
我正在努力使用 C# 中的 Windows Socket 编程,在 Windows 8.1 上使用 .Net 4.5。
所以,我正在做一个非常简单的操作。我正在实现一个客户端-服务器类型的系统,所有这些系统都将在本地机器上运行,通过套接字进行通信。服务器是 Windows 服务,客户端是用户应用程序。
服务根据客户端的请求执行一些 OCR 计算,然后将结果返回给请求进程。该服务有一个监听套接字,它随时接受传入的请求,一个新的套接字被创建并用于响应每个请求。新响应套接字的端口号在请求中指定。这样做是为了让监听套接字能够处理并发请求。
服务的监听套接字工作正常。我能够从连接到侦听套接字的用户应用程序接收请求。当角色互换时会出现问题:服务需要连接到客户端拥有的 Socket,并通过客户端拥有的套接字发送 OCR 结果。让我们进入代码:
服务器端
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()));
}
没有抛出异常,服务继续,好像一切都成功了。
客户端
//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
在客户端调用receiver.Receive() 时抛出异常。以下是异常详情:
类型:SocketException
消息:发送或接收数据的请求被禁止,因为套接字未连接并且(当使用 sendto 调用在数据报套接字上发送时)没有提供地址。
错误代码:10057(未连接套接字)
所以,我被挂断的地方是客户端的套接字未连接。 receiver.Accept() 行是一个阻塞调用,它等待服务器调用responder.Connect()。同时通过双方我看到客户端等待receiver.Accept(),直到服务器调用responder.Connect()。我认为这意味着客户端套接字已接受连接。任何人都可以发现客户端的套接字保持未连接并且抛出此异常的原因吗?
非常感谢所有帮助,非常感谢!
编辑:2015 年 7 月 29 日 5:07p
一些可能有用的附加细节。服务调用后responder.Connect()responder.Connected 为true,并且responder.RemoteEndpoint 是客户端正在侦听的端点(地址和端口号已确认)。
但是,对于客户却不能这样说。在receiver.Accept() 调用通过receiver.Connected 为false 后receiver.RemoteEndpoint 抛出了与上面相同的异常。
进一步挖掘接收者的成员后,我发现 receiver.DontFragment 抛出了 System.NotSupportedException 和消息
不支持此协议版本。
我使用的协议有问题吗?我正在全面使用 TCP。也许它与地址族有关?
【问题讨论】:
-
您的客户端和服务器代码标记错误。另请注意,accept() 返回一个非常重要的值。
-
嗨,马丁。你能详细说明错误标签吗?属于服务器/客户端的代码位于它们各自的粗体部分下方。也许你误解了我对我所包含的代码段的解释
-
标记为“客户端”的代码是 TCP 服务器。标记为“服务器端”的代码是 TCP 客户端。
-
.. 换句话说,接受()调用的对等点是服务器。调用 connect() 的对等方是客户端。
-
无论您的客户端服务器协议发生了什么,我都不知道在哪里可以忽略 accept() 调用的结果。没有这个结果,客户端服务器通信是不可能的。
标签: c# sockets windows-services socketexception