.net http webclient to nodejs server. How to access data? - c#

I have a .net c# client software that sends data like this:
using(WebClient client = new WebClient())
{
string serialisedData = "";
serialisedData = JsonConvert.SerializeObject(myData);
client.Credentials = new NetworkCredential(config.UserData.Username, config.UserData.Password);
byte[] responsebyte = client.UploadData(config.ServerAddress, System.Text.Encoding.UTF8.GetBytes(serialisedData));
}
In nodejs, I currently have this kind of https setup:
_server = https.createServer({
key: fs.readFileSync(`${__dirname}\\bin\\cert\\${_config.sslkey}`, "utf8"),
cert: fs.readFileSync(`${__dirname}\\bin\\cert\\${_config.sslcert}`, "utf8")
}, _listener);
_server.listen(_config.port, "0.0.0.0");
function _listener(req, res) {
let data = []
req.on('data', chunk => {
data.push(chunk)
})
req.on('end', () => {
JSON.parse(data)
})
}
Now my problem. I cant get any data of the req or res object. Both "on" functionts dont fire and I dont know what to do now. Whats the right way to do this in NodeJS? (c# Code cant be changed)
Edit:
Here is the c# Server Code that works. How can I translate that into nodejs?
HttpListener listener = new HttpListener();
listener.Prefixes.Add($"https://+:{Config.Port}/");
listener.AuthenticationSchemes = AuthenticationSchemes.Basic;
listener.Start();
for (; ; )
{
Console.WriteLine("Listening...");
IAsyncResult result = listener.BeginGetContext(new AsyncCallback(DoWork), listener);
result.AsyncWaitHandle.WaitOne();
result = null;
}
private void DoWork(IAsyncResult asyncResult)
{
HttpListener listener = (HttpListener)asyncResult.AsyncState;
HttpListenerContext context = listener.EndGetContext(asyncResult);
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
HttpListenerBasicIdentity identity = (HttpListenerBasicIdentity)context.User.Identity;
string data;
using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
{
data = reader.ReadToEnd();
}
....
More Code
....
string responseSerial = JsonConvert.SerializeObject(responseData);
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseSerial);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}

You lack res.end() somewhere to let node's server know that it should send response back. Before that you can write your actual response. Tested that on your exact C# code and a simplified version of the node server:
var http = require('http');
var _server = http.createServer(_listener);
_server.listen(1234);
console.log( 'started' );
function _listener(req, res) {
let data = []
req.on('data', chunk => {
data.push(chunk)
})
req.on('end', () => {
JSON.parse(data);
res.write('response')
res.end()
})
}

Related

Why TCPClient doesn't receive text data

I have two projects: client and server.
Server code:
static void Main()
{
var listener = new TcpListener(System.Net.IPAddress.Loopback, 13000);
listener.Start();
using (var client = listener.AcceptTcpClient())
{
var stream = client.GetStream();
var textStream = new StreamReader(stream);
while (true)
{
var line = textStream.ReadLine();
if (line == "") continue;
if (line == null) continue;
var clientIp = IPAddress.Parse(line.Split(':').First());
var clientPort = int.Parse(line.Split(':').Last());
var response = new LobbyConnectionResponse(StatusCode.OK, "Connected", new List<Player>(), new Leader("J", Guid.NewGuid()));
SendResponseToClient(clientIp, clientPort, response);
Console.WriteLine(line);
Thread.Sleep(lobbyResponseTimeout);
}
}
listener.Stop();
}
static Task SendResponseToClient(IPAddress ip, int port, LobbyConnectionResponse response)
{
var task = Task.Run(() =>
{
using (var tcpClient = new TcpClient())
{
tcpClient.Connect(ip, port);
var stream = tcpClient.GetStream();
var textStream = new StreamWriter(stream);
string jsonString = JsonSerializer.Serialize(response);
textStream.WriteAsync(jsonString);
stream.FlushAsync();
}
});
return task;
}
Client code:
static void Main()
{
StartListener();
using (var client = new TcpClient())
{
client.Connect("127.0.0.1", 13000);
var stream = client.GetStream();
var textStream = new StreamWriter(stream);
textStream.WriteLine("127.0.0.1:12000");
textStream.Flush();
}
while(true)
Thread.Sleep(1000);
Thread.Sleep(1000);
}
static Task StartListener()
{
var task = Task.Run(() =>
{
var listener = new TcpListener(System.Net.IPAddress.Loopback, 12000);
listener.Start();
while (true)
{
using (var client = listener.AcceptTcpClient())
{
var stream = client.GetStream();
var textStream = new StreamReader(stream);
while (true)
{
if (stream.DataAvailable)
Console.WriteLine("hfdsgdf");
var line = textStream.ReadLine();
if (line == null || line == "") continue;
var response = (LobbyConnectionResponse)JsonSerializer.Deserialize(stream, typeof(LobbyConnectionResponse));
Console.WriteLine(response.Description);
Thread.Sleep(100);
}
}
Thread.Sleep(100);
}
listener.Stop();
});
return task;
}
On the server's console, I had message:"127.0.0.1:12000" but client's console are empty, why client doesn't receive my text data? 0 Exceptions, clients code just looping infinity and every iteration continues because line == null
When I tried to make that on a single port ( server and client), nothing worked. I want that client get my JSON and deserialize it into class instance.
You need to send data through client/stream variable instead of creating a new connection from server to client.
var listener = new TcpListener(System.Net.IPAddress.Loopback, 13000);
listener.Start();
using (var client = listener.AcceptTcpClient())
{
var stream = client.GetStream();
// send response to client
byte[] buffer = Encoding.UTF8.GetBytes("foo");
stream.Write(buffer, 0, buffer.Length);
stream.Close();
}

HttpListener Conflicts with existing registration

I have created a function (ListenForJson) in which I am using HttpListener to get requests and send responses from/to a specific address. I am calling this function inside ActionResult Index() so that it can run in the background. However, since I am calling it in the Homepage of my Webapp, whenever I click on the "Go to Home" button I receive an error the error
Failed to listen on prefix because it conficts with an existing registration on the machine
I understand the reason it happens but I do not know how I can stop it from happening.
public ActionResult Index()
{
Thread thread = new Thread(() => ListenForJson());
thread.Start();
return View();
}
public void ListenForJson()
{
string[] prefixes = new string[] { "https://localhost:44337/" };
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
listener.Prefixes.Add(s);
listener.Start();
while (true)
{
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
//Get Body(Json)
System.IO.Stream body = request.InputStream;
System.Text.Encoding encoding = request.ContentEncoding;
System.IO.StreamReader reader = new System.IO.StreamReader(body, encoding);
string json = reader.ReadToEnd();
JsonObject = DeserializeJson(json);
HttpListenerResponse response = context.Response;
var responseJson = JsonSerialization("SERVICE");
byte[] buffer = new byte[] { };
response.ContentType = "Application/json";
buffer = Encoding.ASCII.GetBytes(responseJson);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
context.Response.Close();
}
}

HttpListener not responding to https request

I've created a small app to get http/https responses:
public static void Listener1(string[] prefixes)
{
if (!HttpListener.IsSupported)
{
Console.WriteLine("Seu ambiente não suporta os recursos da classe HttpListener.");
return;
}
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
HttpListener listener = new HttpListener();
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
Console.WriteLine("Listening...");
HttpListenerContext context = listener.GetContext();
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
string responseString = "<HTML><BODY> Hello world </BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
listener.Stop();
}
And I'm using this prefixes:
string[] url = { "http://localhost:5324/", "https://localhost:5325/" };
When I type http://localhost:5324/ on Chrome, I get the right response, but when using https://localhost:5325/, nothing happens. Not even errors about certificates.

Reading and saving post data

I have been assigned to take over someones position, however I do not really know C#. There is a server (192.268. something ect) that will post data to a site (unknown site, lets say bleh.com)
This is what the posting code snippet looks like:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(
"https://server-ip-here/postlistener?filename=filename.zlib");
req.UseNagleAlgorithm = true;
req.AllowWriteStreamBuffering = true;
req.Method = "POST";
req.Accept = "application/xml";
req.ServicePoint.Expect100Continue = false;
System.Net.ServicePointManager.CheckCertificateRevocationList = false;
req.Proxy = new WebProxy();
filename = "filename.dat";
byte[] postData = File.ReadAllBytes(filename);
Stream stream = req.GetRequestStream();
stream.Write(postData, 0, postData.Length);
stream.Flush();
stream.Close();
req.BeginGetResponse(new AsyncCallback(responseHandler), this);
Which I beleive I get the post request in this form
www.blah.com/upload?filename=file_1234_12389126495129847980.zlib
I am unsure how to listen for post requests and then get the data from them and save them as a file.
Currently I have tried this:
private void Form1_Load(object sender, EventArgs e)
{
listener = new HttpListener();
// listener.Prefixes.Add("http://localhost:8000/");
listener.Prefixes.Add("http://127.0.0.1:8000/");
listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
listener.Start();
listenThread1 = new Thread(new ParameterizedThreadStart(startlistener));
listenThread1.Start();
}
private void startlistener(object s)
{
while (true)
{
// blocks until a client has connected to the server
ProcessRequest();
}
}
private void ProcessRequest()
{
var result = listener.BeginGetContext(ListenerCallback, listener);
result.AsyncWaitHandle.WaitOne();
}
private void ListenerCallback(IAsyncResult result)
{
var context = listener.EndGetContext(result);
Thread.Sleep(1000);
var data_text = new StreamReader(
context.Request.InputStream,
context.Request.ContentEncoding).ReadToEnd();
var cleaned_data = System.Web.HttpUtility.UrlDecode(data_text);
context.Response.StatusCode = 200;
context.Response.StatusDescription = "OK";
MessageBox.Show(cleaned_data);
context.Response.Close();
}
Which listens on the local host (Would sub local host for the website once we establish what it will be).
Not sure how to grab the post though, right now I can only listen for it. Ideally I would only like to accept posts from a specific IP address also.
Any ideas how I can go about grabbing the post data (which will be binary) and saving it as a file?

For each request return response in socket C#

I want to create for each request return response in socket c# and android.
I find the relevant socket and send a request, asking for the data I need.
After sending the request, I receive bytes until it sends the response. Then I stop receiving.
My server will need to handle many clients at once, and preferably multiple requests from a client at once. I need both the client and server to be able to receive messages at any time
I wrote this code:
message = Encoding.UTF8.GetString(dataRec,0,c);
dataRec = new byte[2048];
switch(message)
{
case "list-menu":
sendListMenu();
break;
case "login":
isLogin(message);
break;
}
login method
public void isLogin(string str){
string message = "";
Model_Users users;
dataSend=Encoding.UTF8.GetBytes("send-result");
newsocket.Send(dataSend);
//newsocket.close(); if close not receive
c = newsocket.Receive(dataRec);
message = Encoding.UTF8.GetString(dataRec,0,c);
XmlSerializer xml = new XmlSerializer(typeof(Model_Users));
using (TextReader reader = new StringReader(message))
{
if (reader != null)
{
users = (Model_Users)xml.Deserialize(reader);
MessageBox.Show(users.username);
dataSend = Encoding.UTF8.GetBytes("success-login");
newsocket.Send(dataSend);
newsocket.Close();
}
}
}
android code (client):
socket = new Socket();
socketAddress = new InetSocketAddress(cursor.getString(cursor.getColumnIndex("ip")), 9999);
socket.connect(socketAddress, 10000);
bufferWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
bufferWriter.write(getrequest);
bufferWriter.flush();
String rvdMsgTxt = "";
stringBuilder = new StringBuilder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((rvdMsgTxt = bufferedReader.readLine()).equals("success-login")) {
stringBuilder.append(rvdMsgTxt);
bufferedReader.mark(100);
bufferedReader.reset();
}
bufferWriter.write(XMLConvertor.usersSerializeXML("user", "pass"));
bufferWriter.flush();
But this doesn't work.
this SOLVED by newsocket.Shutdown(SocketShutdown.Send);

Categories