无法通过从 Node.js 到 UWP 应用程序的套接字接收数据

Failed to Receive Data via sockets from Node.js to UWP app

我有一个问题,我尝试通过套接字从 node.js 服务器读取 uwp 应用程序中的字符串,但没有成功。我有一个 System.Runtime.InteropServices.COMException,但我不知道如何修复它。我成功地从 uwp 客户端向节点服务器发送了一个字符串,但我不能做相反的事情。这是我的代码我做错了什么?

这是我的node.js服务器代码

var _HOST = '192.168.1.67';
    var _PORT = 1337;
    var _address;

    var net = require('net');

    var server = net.createServer(function(socket) {
        socket.on('connect', (e) => {
            console.log('client connected ' +
                socket.remoteAddress + ':' +
                socket.remotePort);
        });

        socket.on('data', function(data) {
            console.log('clients says' + ': ' + data);

            var send = "hello client"
            console.log('Server says' + ': ' + send);
            socket.write(send + '\n');


        });

        socket.on('error', function(data) {
            console.log('client on error', data);

        });

        socket.on('close', (e) => {
            console.log('client disconnected');
            socket.end;
        });

    });

这是我的 UWP 代码

  public async Task connect()
        {


            try
            {
                HostName hostName;

                hostName = new HostName(SocksParameters.Host);
                socket.Control.NoDelay = false;
                var cts = new CancellationTokenSource();
                cts.CancelAfter(SampleConfiguration.timeout);

                // Connect to the server
                var connectAsync = socket.ConnectAsync(hostName, SocksParameters.Port);
                var connectTask = connectAsync.AsTask(cts.Token);
                await connectTask;
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.ToString());
                await new MessageDialog("Make sure your Server is open and make sure you follow Instructions To connect localhost").ShowAsync();
                Application.Current.Exit();
            }

        }

public async Task<String> read()
        {
            DataReader reader;
            StringBuilder strBuilder;



            using (reader = new DataReader(socket.InputStream))
            {

                try
                {
                    strBuilder = new StringBuilder();
                    reader.InputStreamOptions = Windows.Storage.Streams.InputStreamOptions.Partial;

                    reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
                    reader.ByteOrder = Windows.Storage.Streams.ByteOrder.LittleEndian;

                    await reader.LoadAsync(256);
                    while (reader.UnconsumedBufferLength > 0)
                    {
                        strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));
                        await reader.LoadAsync(256);//System.Runtime.InteropServices.COMException Exception caught
                    }

                    reader.DetachStream();
                    return strBuilder.ToString();
                }
                catch (Exception e)
                {    
                    return (e.ToString());

                }
            }

        }

  Activated Event   Time    Duration    Thread
    Exception thrown: 'System.Runtime.InteropServices.COMException' in mscorlib.ni.dll ("The I/O operation has been aborted because of either a thread exit or an application request.

The I/O operation has been aborted because of either a thread exit or an application request.
")  0.55s       [18700] <No Name> 

我测试了代码,我发现如果 DataReader 对象 reader 没有更多数据可以读取,代码行 await reader.LoadAsync(256); 将一直等待直到有新消息从服务器发送,DataReader 可以读取它。在您的代码中,如果来自服务器的数据大小小于 256,则您第二次调用 LoadAsync 方法可能会导致问题。

 await reader.LoadAsync(256);
 while (reader.UnconsumedBufferLength > 0)
 {
     strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));     
     await reader.LoadAsync(256);
      //System.Runtime.InteropServices.COMException Exception caught
 }

我这里提供的解决方法是判断是否还有剩余数据可以读取。更新代码如下:

 var loadsize = await reader.LoadAsync(256);
 while (loadsize >= 256)
 {
     loadsize = await reader.LoadAsync(256);
 }
 if (reader.UnconsumedBufferLength > 0)
 {
     strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));
 }

在我看来,您似乎可以使用 StreamReader 而不是 DataReader,这也适用于您的场景,因为它使用起来更简单。代码如下:

Stream streamIn = socket.InputStream.AsStreamForRead();
StreamReader reader = new StreamReader(streamIn);
string response = await reader.ReadLineAsync();
return response;

关于 uwp 中 StreamSocket 的更多详细信息,请参考 official sample