StreamSocketListener只工作一次;第二个呼叫失败

时间:2018-10-09 10:17:15

标签: c# uwp asyncsocket windows-iot-core-10

对于以下问题的任何帮助将不胜感激。我正在使用StreamSocketListener类在运行Windows IoT 10 Core的Raspberry Pi 3上接受TCP / IP连接。

到目前为止,这是我的服务器代码:

static string _maintenancePort = "8888";

public async static void StartListening()
{
    try
    {
        StreamSocketListener listener = new StreamSocketListener();
        var currentSetting = listener.Control.QualityOfService;
        listener.Control.QualityOfService = SocketQualityOfService.LowLatency;
        listener.ConnectionReceived += SocketListener_ConnectionReceived;
        listener.Control.KeepAlive = true;
        await listener.BindServiceNameAsync(_maintenancePort);
    }
    catch (Exception e)
    {
        Log.WriteErrorLog(e);
    }
}

private static async void SocketListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
    try
    {
        Log.WriteDebugLog("Incoming data...");

        Stream inStream = args.Socket.InputStream.AsStreamForRead();
        StreamReader reader = new StreamReader(inStream);
        string request = await reader.ReadLineAsync();

        if (request != null)
        {
            Log.WriteDebugLog("Received : " + request);
        }
    }
    catch (Exception e)
    {
        Log.WriteErrorLog(e);
    }
}

我编写了以下客户端代码以连接到套接字。该代码在另一台计算机上运行。

    // ManualResetEvent instances signal completion.  
    private static ManualResetEvent connectDone = new ManualResetEvent(false);
    private static ManualResetEvent sendDone = new ManualResetEvent(false);
    private static ManualResetEvent receiveDone = new ManualResetEvent(false);

    private static String response = String.Empty;
    public static Socket client;

    public static string SendMessageToClient(string ip, int port, string message, bool expectResponse)
    {
        // Connect to a remote device.  
        try
        {
            // Establish the remote endpoint for the socket.  

            IPAddress ipAddress = IPAddress.Parse(ip);
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP socket.  
            client = new Socket(ipAddress.AddressFamily,SocketType.Stream, ProtocolType.Tcp);

            // Connect to the remote endpoint.  
            client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
            connectDone.WaitOne();

            message += "^" + expectResponse.ToString();

            // Send test data to the remote device.  
            Send(client, message);
            sendDone.WaitOne();

            // Receive the response from the remote device.  
            if (expectResponse)
            {
                Receive(client);
                receiveDone.WaitOne();
            }

            // Release the socket.  
            client.Shutdown(SocketShutdown.Both);
            client.Close();

            return response;
        }
        catch (Exception e)
        {
            Log.Write(e, false);
            return "";
        }
    }

    private static void Send(Socket client, String data)
    {
        // Convert the string data to byte data using ASCII encoding.  
        byte[] byteData = Encoding.ASCII.GetBytes(data);

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

    private static void SendCallback(IAsyncResult ar)
    {
        try
        {
            // Retrieve the socket from the state object.  
            Socket client = (Socket)ar.AsyncState;

            // Complete sending the data to the remote device.  
            int bytesSent = client.EndSend(ar);
            Log.WriteSingleMessage(String.Format("Sent {0} bytes to server.", bytesSent), false);

            // Signal that all bytes have been sent.  
            sendDone.Set();
        }
        catch (Exception e)
        {
            Log.Write(e, false);
        }
    }
}

客户端代码由按钮单击事件触发。我面临的问题是上面的服务器代码只能运行一次。如果我将带有客户端代码的消息发送到服务器,则服务器将处理完美字符串。但是,如果我第二次按下该按钮,则会触发SocketListener_ConnectionReceived事件,但是没有数据传入。我为ConnectionReceived尝试了多个类,但是它们的行为都相同。

我在Raspberry Pi上用netstat检查了服务器是否正在监听。

  

TCP 0.0.0.0:8888 0.0.0.0:0侦听

甚至创建了子进程来处理连接,正如您期望从异步调用中进行的那样。客户端代码在收到已发送数据的消息(waitOne())并且客户端计算机上的套接字更改为CLOSE_WAIT后,关闭套接字。

  

TCP 10.0.102.10:8888 10.0.100.11:31298 CLOSE_WAIT
  建立TCP 10.0.102.10:8888 10.0.100.11:31299

任何人都可以帮助我,并为我指出我做错了正确的方向。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

您可以尝试对套接字客户端使用同步方法而不是异步方法。它会工作。请参考以下代码:

    public void SendMessageToClientSync(string ip, int port, string message, bool expectResponse)
    {
        // Data buffer for incoming data.  
        byte[] bytes = new byte[1024];

        // Connect to a remote device.  
        try
        {
            // Establish the remote endpoint for the socket.  
            // This example uses port 11000 on the local computer.  
            IPAddress ipAddress = IPAddress.Parse(ip);
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);

            // Create a TCP/IP  socket.  
            Socket sender = new Socket(ipAddress.AddressFamily,
                SocketType.Stream, ProtocolType.Tcp);

            // Connect the socket to the remote endpoint. Catch any errors.  
            try
            {
                sender.Connect(remoteEP);

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

                // Encode the data string into a byte array.  
                byte[] msg = Encoding.ASCII.GetBytes(message);

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

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

                // Release the socket.  
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();

            }
            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());
            }

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