UWP 应用无法接收,只能发送,使用套接字

UWP app cannot receive, only send, using sockets

我目前正在开发一个 UWP 应用程序,它应该具有作为 TCP 服务器(使用端口)的能力,以便客户端可以通过其他设备连接到它并发送请求,服务器响应数据。 我遵循了 :Microsoft site 上的 Socket 示例并获得了示例代码(其中服务器和客户端都在同一个应用程序中)

我更改了 IP 地址和端口,以便我可以在 2 台不同的机器上使用直接连接的应用程序,我还制作了单独的简单客户端应用程序,使用来自 Here

的示例代码

现在问题如下:UWP app可以和微软sample提供的自己的客户端方法成功通信,但是无法和我做的console client程序通信,在other上是运行。 UWP确实可以连接客户端,也可以发送数据,但是不能接收数据,函数streamReader.ReadLineAsync();会无限等待,仅此而已。 我如何让 UWP 应用程序获取客户端发送的消息以及我可能做错了什么?

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


}

这是客户端应用程序的源代码:

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

}

}

自己找到答案:主要问题是服务器程序中的 ReadLineAsync():它等待并收集所有流,直到它到达行尾字符。在这种情况下,永远不会发送行尾,因此服务器一直在无限等待。 最简单的修复是在客户端,只需在数据包末尾添加行尾,如下所示:

之前:

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

之后:

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

还有一件事值得一提:当前 StreamSocketListener_ConnectionReceived 只能发送一次,然后将 outputStream.CanWrite 设置为 false。 这可以通过从写入和读取函数中删除 using() 来解决,如下所示: 之前:

PS!手动冲洗也被自动冲洗取代。

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

之后:

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

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

希望有一天能对某人有所帮助。