Using socket to cmmunicate node app to c# service - sockets

[Sorry for my bad English]
Hi!
I have to communicate between a node.js application [client side] and c# application [server side].
Each side sends pings to the other, on TCP protocol.
I Successed to create both client and server side, but I have to problems:
after the first ping from the client to the server, the client throws an error:
This socket has been ended by the other party
What i'm doing wrong?
The server reads the incomeing pings into a large buffer.
When I decode it to string, I get string with length of 4096.
How I read the excact message length?
This is the server side code: [c#, .NET 6]
using System.Net;
using System.Net.Sockets;
using System.Text;
Console.WriteLine("Start...");
CancellationTokenSource cts = new();
TcpListener listener = new(IPAddress.Any, 11111);
try
{
listener.Start();
Console.WriteLine("Listining...");
var clientCounter = 0;
var ct = cts.Token;
while (!ct.IsCancellationRequested)
{
using TcpClient client = await listener.AcceptTcpClientAsync(ct)
.ConfigureAwait(false);
using NetworkStream stream = client.GetStream();
_ = PrintUploadedData(stream, ct);
_ = PushData(stream, ct);
clientCounter++;
Console.WriteLine("New client ({0}) connected", clientCounter);
}
}
finally
{
cts.Cancel();
listener.Stop();
}
async Task PrintUploadedData(NetworkStream stream, CancellationToken ct)
{
var buf = new byte[4096];
while (!ct.IsCancellationRequested)
{
var timeout = CancellationTokenSource.CreateLinkedTokenSource(
ct,
new CancellationTokenSource(TimeSpan.FromMinutes(3)).Token);
try
{
var amountRead = await stream.ReadAsync(buf, timeout.Token);
if (timeout.IsCancellationRequested)
{
Console.Error.WriteLine("No Message.");
break;
}
if (amountRead == 0) break; //end of stream.
var message = Encoding.UTF8.GetString(buf);
Console.WriteLine(message);
}
catch (OperationCanceledException)
{
Console.Error.WriteLine("Time out");
break;
}
}
}
async Task PushData(NetworkStream stream, CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
var messageToSend = DateTime.Now.TimeOfDay.ToString();
var messageBytes = Encoding.UTF8.GetBytes(messageToSend);
await stream.WriteAsync(messageBytes, ct).ConfigureAwait(false);
await Task.Delay(TimeSpan.FromSeconds(15), ct);
}
}
And the client side code [node.js]:
import { Socket } from 'net';
var client = new Socket();
client.on('connect', () => console.log("CONNECTED"));
client.on('data', data => console.log("data", data.toString()));
client.on('error', err => console.error(err));
client.connect(11111, "127.0.0.1");
printMessages();
async function printMessages() {
for (let i = 0; i < 10; i++) {
client.write('Ping ' + i);
await sleep(4000);
}
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

Related

How to use Dart socket onError as inline function?

I have dart socket that gets very long data. Lucky the third party add '\r\n' end of the data, so I can close when I find last data has '\r\n'.
In weeks I am trying to get long data due server problem. Before I used to waiting endlessly to server closes the connection (sometime took me 10 to 12 min)
Now seems everything works but a small problem. I used to get onError and onDone using void function. But I am using aqueduct so I need to return long data after I receive from server as a response.
In my below full code its keep printing "Server_Error". If I comment below data seems everything works. But my problem is that I need to return error data as well.
onError: () {
print("Server_Error");
},
onDone: () {
_socket.destroy();
},
cancelOnError: true);
If I comment above part I can print the long data.
My question is that, based on my scenario how to use Dart socket onError as inline function?
import 'dart:io';
import 'dart:convert';
import 'dart:typed_data';
Socket _socket;
String _reply;
String _testValue = "";
main() async {
String _queryA = “QueryLongData”;
await Socket.connect("192.168.22.120”, 3000).then((Socket sock) {
_socket = sock;
_socket.write('$_queryA\r\n');
_socket.listen((data) {
final List<int> byteArray = data;
_reply = String.fromCharCodes(byteArray);
int dataLen = _reply.length;
int carriageReturnPosition = dataLen - 2;
int newLinePosition = dataLen - 1;
_testValue = _testValue + _reply;
if (_reply.substring(carriageReturnPosition, newLinePosition) == '\r' &&
_reply.substring(newLinePosition, dataLen) == '\n') {
_socket.close();
print("Data: $_testValue"); // means return data
}
}, onError: () {
print("Server_Error");
},
onDone: () {
_socket.destroy();
},
cancelOnError: true);
}).catchError((e) {
print("Server_Error");
});
if(_socket.done == true) {
print("Exiting...");
exit(0);
}
}
<!-- language: dart -->
String _queryA = "QueryLongData";
Socket.connect("192.168.22.120", 3000).then((Socket sock) {
_socket = sock;
_socket.write("$_queryA\r\n");
_socket.listen((data) {
final List<int> byteArray = data;
_reply = String.fromCharCodes(byteArray);
int dataLen = _reply.length;
int carriageReturnPosition = dataLen - 2;
int newLinePosition = dataLen - 1;
_testValue = _testValue + _reply;
if (_reply.substring(carriageReturnPosition, newLinePosition) == "\r" &&
_reply.substring(newLinePosition, dataLen) == "\n") {
_socket.close();
print("Data: $_testValue"); // means return data
}
}, onError: () => print("Server_Error"),
onDone: () => _socket.destroy(),
cancelOnError: true);
}).catchError((e) => print("Server_Error"));
if( ( await _socket.done enter code here) == true) {
print("Exiting...");
exit(0);
}

Sending udp packets using chrome.socket.udp

I was creating a chrome extension in which i am using chrome.socket.udp. I am following this tutorial but i don't see any data sent.
This is my code..
//var socketId;
var address = "127.0.0.1";
var port = 6454;
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2);
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i<strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return bufView;
}
function sendPackets(){
console.log("sending packets");
chrome.sockets.udp.create({}, function(socketInfo) {
// The socket is created, now we can send some data
var socketId = socketInfo.socketId;
console.log(socketId);
chrome.sockets.udp.send(socketId, str2ab("hello"),
'127.0.0.1', 1337, function(sendInfo) {
console.log("packets sent");
console.log("sent " + sendInfo.bytesSent);
});
});
}
document.getElementById('send').addEventListener('click', sendPackets);
this is the output i am getting in console...
sending packets background.js:16
165 background.js:20
And there is no sign of sent data ....plz help...

Dart HTML Server. How do I have the server refuse more than one client connection?

I'm writing a web application that is to be used by only one client and want to accept only one connection to the server. The LAN will be confined to an aircraft. I'm really new to Dart, HTML etc. How can I refuse multiple connections to the server?
Here's my code fir the HTTP server -
class MicroServer {
var address;
var port;
var httpServer; // global
MicroServer(this.address, this.port) {
final HTTP_ROOT_PATH = Platform.script.resolve('../build/web').toFilePath();
final virDir = new VirtualDirectory(HTTP_ROOT_PATH)
..jailRoot = false
..allowDirectoryListing = true;
HttpServer.bind(address, port)
.then((httpserver) {
httpServer = httpserver;
httpserver.listen((request) {
virDir.serveRequest(request);
});
});
}
}
Dart is single-threaded, so you can safely use check a variable to see if there's a current connection:
bool hasClient = false;
HttpServer.bind(address, port)
.then((httpserver) {
httpServer = httpserver;
httpserver.listen((request) {
if (hasClient) {
sendBusyPage(request);
} else {
hasClient = true;
virDir.serveRequest(request);
hasClient = false;
}
});
});
}
I have found that the code below works so far. I could also have taken advantage of
if(request.session.isNew) // then grab the session.id etc.
but it's just as easy to use the session.id variable since I will use it anyway.
class MicroServer {
var address;
var port;
var httpServer;
var sessionID; // null until first request received
MicroServer(this.address, this.port) {
final HTTP_ROOT_PATH = Platform.script.resolve('../build/web').toFilePath();
final virDir = new VirtualDirectory(HTTP_ROOT_PATH)
..jailRoot = false // process links will work
..followLinks = true
..allowDirectoryListing = true;
HttpServer.bind(address, port)
.then((httpserver) {
httpServer = httpserver;
httpserver.idleTimeout = null;
print("micro server started on ${httpserver.address}:${httpserver.port}");
httpserver.listen((request) {
if(sessionID == null) {
sessionID = request.session.id;
virDir.serveRequest(request);
} else if(sessionID == request.session.id){
virDir.serveRequest(request);
} else {
request.response.writeln('ERROR - Connection is in use.');
request.response.close();
request.session.destroy();
}
});
}).catchError((e) => print(e.toString()));
}
}

Async POST fails on WP7 and F#

When I do let! read = from.AsyncRead buf in F#, it blocks and doesn't return until the TCP socket is dead. Why? And how do I fix it?
Its code:
module StreamUtil
open System.IO
/// copy from 'from' stream to 'toStream'
let (|>>) (from : Stream) (toStream : Stream) =
let buf = Array.zeroCreate<byte> 1024
let rec doBlock () =
async {
let! read = from.AsyncRead buf
if read <= 0 then
toStream.Flush()
return ()
else
do! toStream.AsyncWrite(buf, 0, read)
return! doBlock () }
doBlock ()
It's being called from this code:
use fs = new FileStream(targPath, FileMode.CreateNew, FileAccess.ReadWrite)
do! req.InputStream |>> fs
and requested over HTTP with this code from Windows Phone 7.1 emulator:
public void Send()
{
var b = new UriBuilder(_imageService.BaseUrl) {Path = "/images"};
var req = WebRequest.CreateHttp(b.Uri);
req.ContentType = "image/jpeg";
req.Method = "POST";
var imgLen = SelectedImage.ImageStream.Length;
req.Headers[HttpRequestHeader.ContentLength] = imgLen.ToString(CultureInfo.InvariantCulture);
req.Accept = "application/json";
req.BeginGetRequestStream(RequestReady, new ReqState(req, imgLen));
}
void RequestReady(IAsyncResult ar)
{
var state = (ReqState)ar.AsyncState;
var req = state.Request;
var reqStream = req.EndGetRequestStream(ar);
SmartDispatcher.BeginInvoke(() =>
{
using (var sw = new StreamWriter(reqStream))
using (var br = new BinaryReader(SelectedVoucher.ImageStream))
{
var readBytes = br.ReadBytes(state.ImgLen);
// tried both 2
sw.Write(readBytes);
//sw.Write(Convert.ToBase64String(readBytes));
sw.Flush();
sw.Close();
}
req.BeginGetResponse(ResponseReady, req);
});
}
// WHY IS IT YOU ARE NOT CALLED???
void ResponseReady(IAsyncResult ar)
{
try
{
var request = (HttpWebRequest)ar.AsyncState;
var response = request.EndGetResponse(ar);
SmartDispatcher.BeginInvoke(() =>
{
var rdr = new StreamReader(response.GetResponseStream());
var msg = rdr.ReadToEnd();
var imageLocation = response.Headers["Location"];
Debug.WriteLine(msg);
Debug.WriteLine(imageLocation);
});
}
catch (WebException ex)
{
Debug.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
Unsuccessfully. The ResponseReady callback is never reached.
Meanwhile, this code works excellent:
open System
open System.Net.Http // WebAPI nuget
let sync aw = Async.RunSynchronously aw
let postC<'a> (c : HttpClient) (r : Uri) (cont : HttpContent) =
let response = sync <| Async.AwaitTask( c.PostAsync(r, cont) )
let struc:'a = sync <| deserialize<'a> response
response, struc
let withContent<'a> (fVerb : (HttpClient -> Uri -> HttpContent -> _ * 'a))=
let c = new HttpClient()
fVerb c
[<Test>]
let ``POST /images 201 + Location header`` () =
let post = withContent<MyImage> postC
let bytes = IO.File.ReadAllBytes("sample.jpg")
let hash = SHA1.Create().ComputeHash(bytes) |> Convert.ToBase64String
let pic = new ByteArrayContent(bytes)
pic.Headers.Add("Content-Type", "image/jpeg")
pic.Headers.Add("X-SHA1-Hash", hash)
let resp, ri = (resource "/images", pic) ||> post
resp.StatusCode =? Code.Created
ri.sha1 =? hash
mustHaveHeaders resp
I couldn't get Fiddler2 working with WP7.
EDIT: Welcome to a yak. I've moved onto greener pastures myself ;)
YOu should put the bytes into the before sending and using BufferStream INput output

Writing to sockets

I have trouble understanding the reason for the error I get when the user tries to write anything to the server:
TypeError: Object #<identifyClient> has no method 'write'
at writeToAll (/root/node/mud/server.js:13:15)
Why does identifyClient() complaints about the write(), while it happens in the writeToAll() (line 15 has comment next to it)? identifyClient() really only sets the name for the client, and should not be concerned what happens in the writeToAll().
var net = require("net");
var clients = [];
function identifyClient(client) {
this.name = null;
this.client = client;
}
function writeToAll(data, client) {
for (var i = 0; i < clients.length; i++) {
if (clients[i] != client) {
clients[i].write(data); // This is line 15
}
}
}
var server = net.createServer(function(client) {
var clientID = new identifyClient(client);
clients.push(clientID);
client.on("data", function(data) {
writeToAll(data, client);
});
});
server.listen(4444);
Replace clients[i] with clients[i].client
also you have to remove the client from the clients array once it disconnects.