0
votes

Any help on the issue below would be highly appreciated. I'm using the StreamSocketListener Class to accept TCP/IP connection on my Raspberry Pi 3 running windows IoT 10 Core.

This is my server code so far:

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

I wrote the following client code to connect to the socket. This code runs on another machine.

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

The client code is triggered by a button click event. The problem that I'm facing is that the server code above only works once. If I send a message to the server with the client code, the server processes the string perfect. However, if I hit the button a second time, the SocketListener_ConnectionReceived event is triggered but no data is coming in. I've tried several classes for ConnectionReceived but they all behave the same.

I checked with netstat on the Raspberry Pi if the server is listening and it is.

TCP 0.0.0.0:8888 0.0.0.0:0 LISTENING

Even child processes are created for handling the connection as you would expect from an Async calls. The client code closes the socket after it received a message that the data has been send (waitOne()) and the socket on the client machines changes to 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 ESTABLISHED

Can anyone help me out and point me in the right direction as to what I'm doing wrong. any help would be highly appreciated.

1
Really strange. Just for the sake of not being rude, I added 'dear all' to the top of my question but it was removed twice. My sincere apoligies :)Walyunga
This case is windows-iot-core-10 related, please add the tag for this case.CoCaIceDew
Nothing seems to reset your events in the client. Without those being reset, I'd expect the second and subsequent attempts to run that code to have "issues".Damien_The_Unbeliever

1 Answers

0
votes

You can try to use synchronous methods instead asynchronous methods for socket client. It will work. Please refer to following code:

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