为什么Socket.Receive在远程主机断开连接时抛出SocketException(10054)?

时间:2012-12-02 05:48:42

标签: c# .net

我曾经用C编写套接字程序,无法理解上述原因。

我的服务器在接收调用时阻塞,当它返回0时,我会跳出while循环并关闭该线程。

 public class MyServer {

    public MyServer() {
    }

    public void Init() {
        ThreadPool.QueueUserWorkItem(StartListening);
        while (true) {
            Console.Read();
        }
    }

    public void StartListening(Object state) {
        // Establish the local endpoint for the socket.
        IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
        IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
        Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        try {
            // Bind the socket to the local endpoint and listen for incoming connections.
            listener.Bind(localEndPoint);
            listener.Listen(100);

            while (true) {
                Console.WriteLine("Waiting for a connection...");
                // get connection
                Socket client = listener.Accept();
                // push client to another thread
                ThreadPool.QueueUserWorkItem(HandleClient, client);
            }

        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }
    }

    private void HandleClient(Object obj) {
        // Get the socket that handles the client request.
        Socket client = (Socket)obj;

        // Create the state object.
        StateObject state = new StateObject();
        state.workSocket = client;

        try {
            while (true) {
                int bytesRead = client.Receive(state.buffer);
                Console.WriteLine("bytesRead=" + bytesRead);

                // remote dc.
                if (bytesRead == 0)
                    break;

                String content = Encoding.ASCII.GetString(state.buffer, 0, bytesRead);
                Console.WriteLine("Read {0} bytes from socket. \n Data : {1}", content.Length, content);
                client.Send(state.buffer, 0, state.buffer.Length, 0);
            }
        } catch (SocketException e) {
            Console.WriteLine("SocketException : {0}", e.ToString());
        }
        client.Shutdown(SocketShutdown.Both);
        client.Close();
    }


    private void Send(Socket handler, String data) {
        byte[] byteData = Encoding.ASCII.GetBytes(data);

        // Begin sending the data to the remote device.
        //handler.BeginSend(byteData, 0, byteData.Length, 0, new AsyncCallback(SendCallback), handler);

    }
}

但是,当我单击客户端的关闭按钮(“x”)时,服务器的Receive调用将抛出SocketException。根据{{​​3}},这不应该发生,因为我已经满足了面向连接的部分(见上文)和客户端关闭部分(见下文)条件。

Client.cs (pseudo):

public class MyClient {
public void Init() {
    byte[] bytes = new byte[1024];
    Socket sender = null;
    try {
        IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
        IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);
        sender = new Socket(AddressFamily.InterNetwork,
           SocketType.Stream, ProtocolType.Tcp);
        sender.Connect(remoteEP);

        Console.WriteLine("Socket connected to {0}",
            sender.RemoteEndPoint.ToString());

        while (true) {
            // Encode the data string into a byte array.
            String input = Console.ReadLine();
            byte[] msg = Encoding.ASCII.GetBytes(input);

            // Send the data through the socket.
            int bytesSent = sender.Send(msg);

            // Receive the response from the remote device.
            int bytesRec = sender.Receive(bytes);
            Console.WriteLine("Echoed test = {0}",
                Encoding.ASCII.GetString(bytes, 0, bytesRec));
        }



    } catch (ArgumentNullException ane) {
        Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
    } catch (SocketException se) {
        Console.WriteLine("SocketException : {0}", se.ToString());
    } catch (Exception e) {
        Console.WriteLine("Unexpected exception : {0}", e.ToString());
    } finally {
        sender.Shutdown(SocketShutdown.Both);
        sender.Close();
    }
}

}

我对finally块的浅层理解是它将始终执行。但这似乎并非如此。

那么,我在这里做错了什么?我是否应该捕获异常,关闭服务器端的客户端套接字然后继续,忽略它?但我更愿意,如果没有抛出异常。

0 个答案:

没有答案