0

I'm currently developing an UWP app which should have capability to be as a TCP server (using ports) so client can connect to it via other device and send requests and server responds with data. I followed the Socket example on :Microsoft site, and got sample code working (in which server and client are both in same app)

I changed IP addresses and ports so i could use apps on 2 different machines with direct connection, I also made separate simple client application, using sample code from Here

Now problem is as follows: UWP app can successfully communicate with its own client method provided by Microsoft's sample, but is unable to communicate with console client program I made and was running on other. UWP can indeed connect with client and also send data, but it cannot receive data, the function streamReader.ReadLineAsync(); will wait infinitely long and that's all. How do i make UWP app get the message client is sending and what i might be doing wrong ?

public sealed partial class MainPage : Page
{
    static string PORT_NO = "1300";
    const string SERVER_IP = "192.168.0.10";

    public MainPage()
    {
        this.InitializeComponent();
        outputText.Text = "Helloo";
        StartConnection(SERVER_IP, PORT_NO);
        //StartClient();

    }

    public async void StartConnection(string net_aadress, string port_nr)
    {
        try
        {
            var streamSocketListener = new StreamSocketListener();

            // The ConnectionReceived event is raised when connections are received.
            streamSocketListener.ConnectionReceived += this.StreamSocketListener_ConnectionReceived;

            // Start listening for incoming TCP connections on the specified port. You can specify any port that's not currently in use.
            await streamSocketListener.BindServiceNameAsync(port_nr);

            outputText.Text = "server is listening...";
        }
        catch (Exception ex)
        {
            Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
            outputText.Text = (webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
        }
    }

    private async void StreamSocketListener_ConnectionReceived(Windows.Networking.Sockets.StreamSocketListener sender, Windows.Networking.Sockets.StreamSocketListenerConnectionReceivedEventArgs args)
    {

        string request = "password";
        string second;
        /*
        using (var streamReader = new StreamReader(args.Socket.InputStream.AsStreamForRead()))
        {
            request = await streamReader.ReadLineAsync();
        }
        */
        //await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server received the request: \"{0}\"", request)));

        // Echo the request back as the response.
        using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
        {
            using (var streamWriter = new StreamWriter(outputStream))
            {
                await streamWriter.WriteLineAsync(request);
                await streamWriter.FlushAsync();
            }
        }

        using (var streamReader = new StreamReader(args.Socket.InputStream.AsStreamForRead()))
        {
            second = await streamReader.ReadLineAsync();
        }


        using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
        {
            using (var streamWriter = new StreamWriter(outputStream))
            {
                await streamWriter.WriteLineAsync(second);
                await streamWriter.FlushAsync();
            }
        }

        //await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add(string.Format("server sent back the response: \"{0}\"", request)));

        sender.Dispose();

        //await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => this.serverListBox.Items.Add("server closed its socket"));
    }

    private async void StartClient()
    {
        try
        {
            // Create the StreamSocket and establish a connection to the echo server.
            using (var streamSocket = new Windows.Networking.Sockets.StreamSocket())
            {
                // The server hostname that we will be establishing a connection to. In this example, the server and client are in the same process.
                var hostName = new Windows.Networking.HostName("localhost");

                //this.clientListBox.Items.Add("client is trying to connect...");

                await streamSocket.ConnectAsync(hostName, PORT_NO);

                //this.clientListBox.Items.Add("client connected");

                // Send a request to the echo server.
                string request = "Hello, World!";
                using (Stream outputStream = streamSocket.OutputStream.AsStreamForWrite())
                {
                    using (var streamWriter = new StreamWriter(outputStream))
                    {
                        await streamWriter.WriteLineAsync(request);
                        await streamWriter.FlushAsync();
                    }
                }

                //this.clientListBox.Items.Add(string.Format("client sent the request: \"{0}\"", request));

                // Read data from the echo server.
                string response;
                using (Stream inputStream = streamSocket.InputStream.AsStreamForRead())
                {
                    using (StreamReader streamReader = new StreamReader(inputStream))
                    {
                        response = await streamReader.ReadLineAsync();
                    }
                }

                await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                     () =>
                     {
                         outputText.Text = "Client got back " + response;
                     }
                 );



            }

            //this.clientListBox.Items.Add("client closed its socket");
        }
        catch (Exception ex)
        {
            Windows.Networking.Sockets.SocketErrorStatus webErrorStatus = Windows.Networking.Sockets.SocketError.GetStatus(ex.GetBaseException().HResult);
            //this.clientListBox.Items.Add(webErrorStatus.ToString() != "Unknown" ? webErrorStatus.ToString() : ex.Message);
        }
    }


}

Here is source code for Client application:

{
class Program
{
    const int PORT_NUMBER = 1300;
    const string SERVER_IP = "192.168.0.10";
    static void Main(string[] args)
    {
        string textToSend = DateTime.Now.ToString();
        string password = "Madis on loll";
        string receiveddata;
        try
        {
            Console.WriteLine("Client progrm started");
            TcpClient client = new TcpClient(SERVER_IP, PORT_NUMBER);
            NetworkStream nwStream = client.GetStream();

            //System.Threading.Thread.Sleep(500);
            //see, how long is packet

            byte[] bytesToRead = new byte[client.ReceiveBufferSize];
            int bytesRead = nwStream.Read(bytesToRead, 0, client.ReceiveBufferSize);
            Console.WriteLine("Received : " + Encoding.ASCII.GetString(bytesToRead, 0, bytesRead));


            byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
            Console.WriteLine("Sending : " + password);
            nwStream.Write(password2, 0, password2.Length); //sending packet

            byte[] receiveddata2 = new byte[client.ReceiveBufferSize];
            int receiveddatalength = nwStream.Read(receiveddata2, 0, client.ReceiveBufferSize);
            Console.WriteLine("Received : " + Encoding.ASCII.GetString(receiveddata2, 0, bytesRead));


        }
        catch (Exception ex)
        {
            Console.WriteLine("Connection  error");
        }
    }

}

}

LempsPC
  • 125
  • 1
  • 1
  • 9
  • Did you debug server and find out where the code is stopping? I do not like "using" statements because they do not report all exceptions. I rather use try/catch blocks that properly report ALL exceptions. I bet you will find that you are getting an exception is the server that is not being reported. Debug the Server code yourself. – jdweng Jun 19 '18 at 09:24
  • Thank you for your answer, Yes i Debugged the server code and it is stopping at streamReader.ReadLineAsync(); function, waiting for data which it wont get from console app. Using statements are recommended by default by Microsoft in their UWP sample – LempsPC Jun 19 '18 at 09:30
  • Add additional write statement like "outputText.Text = "server is listening...";" in both client and server and include the time in the output messages. You may be receiving one message and getting stuck when you getting the second message. – jdweng Jun 19 '18 at 09:44
  • In a fact the first version of these 2 apps: client sends its message after connecting and server at first only receives. In that scenario server kept waiting infinitely after connection was established, so even first message didn't come through into server – LempsPC Jun 19 '18 at 10:02

1 Answers1

1

Found answer myself: main problem is with ReadLineAsync() in Server program: it waits and collects all the stream until it gets end of line character. In this case end of line was never sent and therefore server kept waiting infinitely. Simplest fix was on Client side by simply adding end of line at the end of packet, like this:

before:

byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
Console.WriteLine("Sending : " + password);
nwStream.Write(password2, 0, password2.Length); //sending packet

after:

byte[] newLine = Encoding.ASCII.GetBytes(Environment.NewLine);   
byte[] password2 = ASCIIEncoding.ASCII.GetBytes(password);
Console.WriteLine("Sending : " + password);
nwStream.Write(password2, 0, password2.Length); //sending packet
nwStream.Write(newLine,0,newLine.Length);

Also 1 thing worth mentioning: current StreamSocketListener_ConnectionReceived is able to send only once, then it sets outputStream.CanWrite to false. This can be solved by removing using() from writing and reading functions, like this: before:

PS! Manually flushing is also replaced with autoflush.

using (Stream outputStream = args.Socket.OutputStream.AsStreamForWrite())
    {
        using (var streamWriter = new StreamWriter(outputStream))
        {
            await streamWriter.WriteLineAsync(request);
            await streamWriter.FlushAsync();
        }
    }

after:

Stream outputStream = args.Socket.OutputStream.AsStreamForWrite();
var streamWriter = new StreamWriter(outputStream);

streamWriter.AutoFlush = true;
await streamWriter.WriteLineAsync(request);

Hope it helps someone someday.

LempsPC
  • 125
  • 1
  • 1
  • 9