I have a problem i am try reading via sockets a string in uwp app from a node.js server with no success. I got an System.Runtime.InteropServices.COMException and i dont know how to fix it. I manage to send with succes from the uwp client to the node server a string but i can't do the opposite. Here is my code what i am doing wrong?
This is my node.js Server Code
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;
});
});
This is my UWP Code
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>
I tested the code and I found if there is no more data can be read by the DataReader
object reader
, the code line await reader.LoadAsync(256);
will always wait there until new messages send from server and DataReader
can read it. In the code of yours if the size of coming data from server is less than 256, the second time you invoke the LoadAsync
method may lead issues.
await reader.LoadAsync(256);
while (reader.UnconsumedBufferLength > 0)
{
strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));
await reader.LoadAsync(256);
//System.Runtime.InteropServices.COMException Exception caught
}
The workaround I provided here is to judge whether there is data left can be read. Updated code as follows:
var loadsize = await reader.LoadAsync(256);
while (loadsize >= 256)
{
loadsize = await reader.LoadAsync(256);
}
if (reader.UnconsumedBufferLength > 0)
{
strBuilder.Append(reader.ReadString(reader.UnconsumedBufferLength));
}
In my opinion, it seems like you can use StreamReader
which is also work for your scenario instead of DataReader
since it is more simply to use. Code like follows:
Stream streamIn = socket.InputStream.AsStreamForRead();
StreamReader reader = new StreamReader(streamIn);
string response = await reader.ReadLineAsync();
return response;
More details about StreamSocket
in uwp please reference the official sample.