1

I am having problems getting a TCP server to connect. I tried to pull apart the sample and thought I had everything correct. For some reason the server never accepts the incoming connection.

Code:

 public async void StartServer()
    {
        StreamSocketListener listener = new StreamSocketListener();
        listener.ConnectionReceived += OnConnection;
        listener.Control.KeepAlive = true;

        try
        {
            await listener.BindServiceNameAsync(RX_Connection_Port.Text);
        }
        catch
        {

        }
    }

    private async void OnConnection(
       StreamSocketListener sender,
       StreamSocketListenerConnectionReceivedEventArgs args)
    {
        DataReader reader = new DataReader(args.Socket.InputStream);
        try
        {
            while (true)
            {
                // Read first 4 bytes (length of the subsequent string).
                uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
                if (sizeFieldCount != sizeof(uint))
                {
                    // The underlying socket was closed before we were able to read the whole data.
                    return;
                }

                // Read the string.
                uint stringLength = reader.ReadUInt32();
                uint actualStringLength = await reader.LoadAsync(stringLength);
                if (stringLength != actualStringLength)
                {
                    // The underlying socket was closed before we were able to read the whole data.
                    return;
                }

                string recieved = reader.ReadString(actualStringLength);

                SynthPlayback(recieved);

            }
        }
        catch (Exception exception)
        {
            // If this is an unknown status it means that the error is fatal and retry will likely fail.
            if (Windows.Networking.Sockets.SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
            {
                throw;
            }


        }
    }

Any ideas to what I missed. The ipaddress and port are correct in the connection?

Update:

Added a text block to see the error

 public async void StartServer()
    {
        StreamSocketListener listener = new StreamSocketListener();
        listener.ConnectionReceived += OnConnection;
        listener.Control.KeepAlive = true;

        try
        {
            await listener.BindServiceNameAsync(RX_Connection_Port.Text);
        }
        catch (Exception exception)
        {
            if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
            {
                throw;
            }
            ErrorReport.Text = "Start listening failed with error: " + exception.Message;
        }
    }

Result: Start listening failed with error: The specified class was not found.

not sure what is happening. Any ideas?

Update: Narrowing this down. Got the first problem fixed and now have another.When the client connects to the listener it immediately starts to process before data has come in. I need to wait for data to come in not start on the connection. I am basing this off of this block of code:

 while (true)
            {
                uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));

                if (sizeFieldCount != sizeof(uint))
                {
                    // The underlying socket was closed before we were able to read the whole data.
                    return;
                }
                // Read the string.
                uint stringLength = reader.ReadUInt32();

                uint actualStringLength = await reader.LoadAsync(stringLength);//This is where the code breaks.

                if (stringLength != actualStringLength)
                {
                    // The underlying socket was closed before we were able to read the whole data.
                    return;
                }

                ErrorReport.Text = String.Format("Received data: \"{0}\"", reader.ReadString(actualStringLength));
            }

maybe I need to do this differently. I just need a server to sit there and listen to incoming data. Then read the data to a string for use later. I have looked through so many examples my head is spinning. I am in overload. Any one have a snippit of working server class?

  • 2
    Have you tried putting a breakpoint in the empty catch block of the StartServer method to see if its blowing up there? – tobyd Oct 23 '17 at 13:17
  • 1
    putting in a breakpoint is a great idea. Even at the very first lines of the OnConnection and then just do a simple request. It should hit the break point. If it doesnt it means there could be a firewall problem. Also the HTTP Result from the client can also contain more information, expsiecailly if its 4xx - 404 not found, 405 security exception, and others. codeproject.com/articles/1079341/webcontrols See if that helps sort something out? and actual IoT examples here github.com/Microsoft/Windows-universal-samples/tree/master/… – Piotr Kula Oct 23 '17 at 13:59
  • The catch block is where it is blowing up. I put a watch and it stops there. Any ideas based on what the code above shows? Maybe the port text? Should it be a int? – C.mac Oct 23 '17 at 16:06
  • 1
    RX_Connection_Port.Text is your likely culprit, if you swap that for an integer port (as you noticed) that should relieve the specified class not found exception. I can replicate the error on a Win10 UWP after finding out UWP sockets cannot be easily accessed locally, but are fine remotely... – tobyd Oct 23 '17 at 19:08
  • tobyd I was able to fix that. The Text field had not yet populated when I tried to invoke the listener. Connection is now good. Its just getting the data that come in that is failing. – C.mac Oct 23 '17 at 19:10
1

Assuming you are sending a control uint32 saying how many bytes you are about to send, something like in your connected event handler this should get you going.

using(DataReader reader = new DataReader(args.Socket.InputStream))
{
    //get the number of bytes you are expecting
    await reader.LoadAsync(sizeof(uint));
    uint expected = reader.ReadUInt32();

    // then load the buffer with those bytes
    await reader.LoadAsync(expected);
    byte[] buffer = new byte[expected];
    reader.ReadBytes(buffer); // grab them into a buffer

    //output the buffer to the console
    Debug.WriteLine(ASCIIEncoding.ASCII.GetString(buffer));
}

It doesn't handle sending nothing, or expections or anything like that and I am assuming you are sending in Ascii (if not swap that for utf-8 or whatever) but otherwise this should grab your length int then wait until its received all the rest.

My test client was this python 3.4+ code from a remote host (to get over the UWP localhost problem). It breaks the sends to demo the waiting bit.

import socket;

ip, port = 'x.x.x.x', 5001
message = b"What a lot of horses there are in that field"
i = len(message).to_bytes(4, byteorder='big')

sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    sk.connect((ip, port))
    sk.sendall(i)
    sk.sendall(message[0:5])
    sk.sendall(message[5:len(message)])
    reply = sk.recv(4096)
    print(reply)
except Exception as e:
    print(e)

which does the job.
Stop laughing.

Part 2

If you don't know how many bytes you'll be sent you can try the following using the regular System.IO streams API. There are a host of readers and buffers and things but since at this point you are mostly stuck at reading chunks then you should be able to get by with this sort of approach.

private async void OnConnection(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
    const int BufferSize = 64;
    Stream strm = args.Socket.InputStream.AsStreamForRead();
    StringBuilder builder = new StringBuilder();
    byte[] buffer = new byte[BufferSize];
    int read = -1;
    while(read != 0)
    {
        read = strm.Read(buffer, 0, BufferSize);
        builder.Append(ASCIIEncoding.ASCII.GetString(buffer, 0, read));
    }

    Debug.WriteLine(builder.ToString());

    DataWriter writer = new DataWriter(args.Socket.OutputStream);
    writer.WriteString("ok");
    await writer.StoreAsync();
    await writer.DetachStream().FlushAsync();
}

You can adjust that BufferSize const to a suitable value, say if you know you usually get at least 128 bytes, then up it for efficiency. The caller needs to close their end to signal the end of the stream or this will just sit waiting for a while. You can junk the writer bit at the end if you don't need to return anything.

The Python test client code for this was

import socket;

ip, port = 'x.x.x.x', 5001
m1 = b"The quick brown fox jumps over the lazy dog"
m2 = b"another quick brown fox jumps over the lazy dog"
m3 = b"yet another quick brown fox jumps over the lazy dog"

sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
    sk.connect((ip, port))
    sk.sendall(m1)
    sk.sendall(m2)
    sk.sendall(m3)
    sk.shutdown(1)
    print(sk.recv(128))
except Exception as e:
    print(e)
  • I will give this a try. I am sending just a ASCII string into the server. – C.mac Oct 23 '17 at 20:24
  • I tied to use this example you provided(thank you). However when I send the string " this is a test string" to the server it crashes on ----- await reader.LoadAsync(expected); – C.mac Oct 23 '17 at 20:33
  • Do you know what the value of the expected variable is? it should be fairly small. Otherwise what exception are you getting at that point? That test string worked ok in the Python client but I did get a few blow ups sending a poorly formatted uint at the start. – tobyd Oct 23 '17 at 20:52
  • the problem is I don't think I am sending uint at the start to specify the length of the incoming string. I will see if I can find the exception. The string I am sending is a simple ASCII string. No header or delimiter although a delimiter could be added if it would help solve the problem. – C.mac Oct 23 '17 at 20:54
0

this part of code now works as expected.

 public async void StartServer()
    {

        StreamSocketListener listener = new StreamSocketListener();
        listener.ConnectionReceived += OnConnection;
        listener.Control.KeepAlive = false;

        try
        {
            string ServerName = RX_Connection_Port.Text.ToString();
            await listener.BindServiceNameAsync(ServerName);
        }
        catch (Exception exception)
        {
            if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
            {
                throw;
            }
            ErrorReport.Text = "Start listening failed with error: " + exception.Message;
        }
    }

The only problem I am having now is getting the input string and reading it. The string is sent from another device that sends the strings in a format like:

"Hello this is a test string"(without quotes).

All samples I have tried want a uint to specify the string length. Unfortunately this is not an option currently as I cannot control the device output. It sends in plain ASCII strings.

0

I am still working on this and have narrowed it down further but cant figure out what is happening.

The code:

 private async void DataListener_ConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
    {
        DataReader DataListener_Reader;
        StringBuilder DataListener_StrBuilder;
        string DataReceived;

        using (DataListener_Reader = new DataReader(args.Socket.InputStream))
            try
            {
                {
                    DataListener_StrBuilder = new StringBuilder();
                    DataListener_Reader.InputStreamOptions = InputStreamOptions.Partial;
                    DataListener_Reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
                    DataListener_Reader.ByteOrder = ByteOrder.LittleEndian;
                    await DataListener_Reader.LoadAsync(256);
                    while (DataListener_Reader.UnconsumedBufferLength > 0)
                    {
                        DataListener_StrBuilder.Append(DataListener_Reader.ReadString(DataListener_Reader.UnconsumedBufferLength));
                        await DataListener_Reader.LoadAsync(256);
                    }
                    DataListener_Reader.DetachStream();
                    DataReceived = DataListener_StrBuilder.ToString();
                }

                if (DataReceived != null)
                {
                    Debug.WriteLine("[SERVER] I've received " + DataReceived + " from " + args.Socket.Information.RemoteHostName);
                    // ServerResult.Text = "[SERVER] I've received " + DataReceived + " from " + args.Socket.Information.RemoteHostName;
                    ProcessRecievedData(DataReceived); 

                }
                else
                {
                     Debug.WriteLine("Received data was empty. Check if you sent data.");
                }
            }
            catch (Exception exception)
            {

                ServerResult.Text = "Incoming Data failed with error: " + exception.Message;

            }

    }

When the code hits the If(DataRecieved != null), the debug prints the information perfect. However if I try to send the data to another method of print the result in a text box the catch is triggered. If I only use the debug it processes with no problems. Any ideas to what could be causing this. I want to send the data to a text box and also use for other methods. The code does work as I get the incoming data. Just cant do anything with it. What could be causing this?

0

Solved:

 await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                    {
                        this.ServerResult.Text = incoming;
                        SynthPlayback(
                    });

Added this to by code and it fixed the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.