IPC between C# and C++ using named pipes - c#

I have a C++ server application and C# client application, and I want them to communicate with each other using named pipes mechanism.
I want to use a multithreded server (each tread will service a client), I found a working code here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365588(v=vs.85).aspx
It works great with the C++ client from here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365592(v=vs.85).aspx
My goal is to make this C++ server to work with C# client, so I wrote this simple program for the client side:
public static void Main(string[] Args)
{
//Client
var client = new NamedPipeClientStream(".", "mynamedpipe", PipeDirection.InOut);
client.Connect();
StreamReader reader = new StreamReader(client, Encoding.Unicode);
StreamWriter writer = new StreamWriter(client, Encoding.Unicode);
int i = 0;
while (true)
{
writer.WriteLine("Message" + i.ToString() + Char.MinValue);
writer.Flush();
i++;
System.Console.WriteLine(reader.ReadLine());
Console.ReadKey();
}
}
The behavior I expect is :
Client->Server: "Message1"
Server->Client: "default answer from server"
Client->Server: "Message2"
Server->Client: "default answer from server"
Client->Server: "Message3"
Server->Client: "default answer from server"
Client->Server: "Message4"
Server->Client: "default answer from server"
And so on...
Instead, this is the output I get:
Pipe Server: Main thread awaiting client connection on \.\pipe\mynamedpipe
Client connected, creating a processing thread.
Pipe Server: Main thread awaiting client connection on \.\pipe\mynamedpipe
InstanceThread created, receiving and processing messages.
Client Request String:"?????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????
????????????????????????????????????????????????????????????????????????????????
???????????????????????????????????????????????????????????"
Client Request String:"Message0"
After some debugging here are few weird things I noticed:
client.Connect(); causes 2 bytes (not null terminated) to be written to the pipe. this explains the "?????..."
"Messege0" gets written correctly from the client side and the server reads it correctly also, but:
Client side does not seem to read the reply from the server ("default answer from server") correctly - it is stuck on the blocking "reader.ReadLine()" line. I do not think it is because of a bug on the server as the same server seems to work fine with the C++ client.
After closing the server, the message gets to the client. I added
FlushFileBuffers(hPipe);
after
WriteFile()
in the server - it did not help.
Encoding seems to be correct on both sides - Unicode, Little Endien.
Both server and client running on the same Windows machine.
The issue in item number 3, is the most disturbing to me, and I cannot find an explanation.

Related

How to make GrpcChannel use HTTP/2 on MonoAndroid?

I am trying to make request to my server by MagicOnion protocol (it uses transport from gRPC, but deffrent serialization protocol, message pack instead of protobuf).
An simple test client app, working under net5.0 is executing code like this:
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
var address = $"http://{ServerUrl.Host}:5002";
using var channel = GrpcChannel.ForAddress(address);
var myServiceClient = MagicOnionClient.Create<IMyService>(channel);
var result = await myServiceClient.GetMyData();
...and recieves response succesfully. But if I try to execute the same code on Android app, I am seeing this exception message on server logs:
Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2ConnectionErrorException: HTTP/2 connection error (PROTOCOL_ERROR): Invalid HTTP/2 connection preface.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.ParsePreface(ReadOnlySequence`1& buffer, SequencePosition& consumed, SequencePosition& examined)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.TryReadPrefaceAsync()
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2.Http2Connection.ProcessRequestsAsync[TContext](IHttpApplication`1 application)
With logs and traffic dump I can see that the client on .Net 5 uses HTTP/2, but on Android - HTTP/1.1. As I can see, this is the only deifference between requests.
So, how can I make Android (API30, monoandroid10.0) client use HTTP/2?
The resolution is to use another gRPCC implementation lib - Grpc.Core. It provides GrpcChannel class wich is compatible with MagicOnion.
In my case, the library didn't work immediately, throwing the error about libgrpc_csharp_ext loading trouble. To solve this, you also have to add pacakge Grpc.Core.Xamarin.
The usage example:
var channel = new Grpc.Core.Channel(ServerUrl.Host, 5002, Grpc.Core.ChannelCredentials.Insecure);
var myServiceClient = MagicOnionClient.Create<IMyService>(channel);
var result = await myServiceClient.GetMyData();

Multiple Clients on TCPListener C# / Server sending Data [duplicate]

This question already has an answer here:
C# TcpClient: Send serialized objects using separators?
(1 answer)
Closed 4 years ago.
Being a "novice" in C# and C# Network programming I tried to make a simple chat in C# using TCPClient and TCPListener , I've managed to send data from client to server but if I add a second client the server doesnt read his data and i have a second issue I couldn't figure out how to send data from server to client using TCPListener .
Server :
while (true)
{
Socket client = Server.AcceptSocket();
Console.WriteLine("Connection accepted from " + client.RemoteEndPoint);
count += 1;
string msg;
byte[] buf = new byte[1024];
client.Receive(buf);
msg = Encoding.UTF8.GetString(buf);
Console.WriteLine("Received... " + msg + "");
}
}
Client :
while (true)
{
Console.WriteLine("Connected");
Console.Write("Enter the string to be transmitted : ");
String msg = Console.ReadLine();
Stream stm = tcpClient.GetStream();
ASCIIEncoding asen= new ASCIIEncoding();
byte[] send = asen.GetBytes(msg);
Console.WriteLine("Transmitting.....");
stm.Write(send, 0, send.Length);
if (msg == "/Q"){
tcpClient.Close();
Environment.Exit(0);
}
}
If you see any absurdity / Mistake in my code please tell me i'm here to learn !
Thank You
Where I am not the best with C# this post Server Client send/receive simple text how to create C# simple server, and should fix the first issue of the client not being able to recive data from the server.
As for the second issue not being able to support mulitple connections, this could be to do with there is no threading, so the question is do you want to create a C# webserver or a C# application which utilizes TCP communication to a server.
if the answer is the latter, then I would look to installing tried and tested server such a Apache or Nginx. this will allow the server to handle multiple requests on your behalf and skip having to handle multiple connections and threads, while you are learning more about the client server relationship. also this article may help setting up the fastcgi environment for the appliction http://www.mono-project.com/docs/web/fastcgi/nginx/
otherwise then you will have to look at how to handle multiple clients which this post looks like it could help TCP server with multiple Clients

websocket-sharp how to work with socketio server and send "emit" request

i can connect to my socketio server, but how can i send a requst with params?
My socketio server listen event
socket.on('init', ( data ) => {
console.log('init', data);
});
on client side i tryed to do this
_socket.OnMessage += (sender, e) =>
{
Console.WriteLine("message: {0} {1}", e.IsBinary, e.Data);
_socket.Send(MakePacket("init", new Init
{
key = "1",
room = "eq",
type = "s"
}.ToJson())
);
};
private string MakePacket(string e, string data)
{
return new[] {e, data}.ToJson();
}
so i send json to server
["init", {"type":"s","key":"1","room":"eq"}]
But server wont react at this packet. Server working fine, i have problem only with call this event at C#. What i do wrong?
The problem is that socket.io is not plain websocket, but a custom protocol on top of websocket (or also on top of HTTP long polling as a fallback and on initialization). That means to speak with a socket.io server you have to encode your data and messages just like socket.io would do it. Here seems to be some documentation about how it works.
Alternatives:
Use a socket.io library on client side - but I don't know if one exists
Work with raw websockets on server side
C# has socketio library but i have some issues that i can't find answers at and there are no support at all. So i switched to websocket-sharp.
Afer some reseach of debug info from socketio server i found the answer. If i send this string all works fine
42["init", {"type":"s","key":"1","room":"eq"}]
Just add 42 before json and all will work fine. Magic.
I think this 42 number is like your current connect status or something like this. Because when you just connect to socketio server it's send string with 0 before json.

How to use TCP Client in Android without Sockets?

I have a TCP server in C# and also a TCP Client in C#, now I need a TCP Client in Android too.
All the examples i found are related to sockets, but I'm using a simple TCP Client so they don't work.
Right now my C# TCP Client is like that:
TcpClient client = new TcpClient("127.0.0.1", 1200);
NetworkStream n = client.GetStream();
Console.WriteLine("Insert name");
string name= Console.ReadLine();
byte[] message = Encoding.Unicode.GetBytes(name);
n.Write(message, 0, message.Length);
Is there a corresponding of this function in Android?
This is the actual android client i'm trying and that doesn't work
InetAddress serverAddr = InetAddress.getByName("127.0.0.1");
socket = new Socket(serverAddr, 1200);
EditText et = (EditText) findViewById(R.id.EditText01);
String str = et.getText().toString();
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
out.println(str);
First, this line:
InetAddress serverAddr = InetAddress.getByName(127.0.0.1);
contains a syntax error. It should be:
InetAddress serverAddr = InetAddress.getByName("127.0.0.1");
Second, the address "127.0.0.1" refers to the "same machine" that executes the client. In the case of your C# program, the server runs on the same machine as the client, so it worked. But in the case of Android, there in no server that runs on the "same machine", which is your Android phone (event if it is emulated, 127.0.0.1 refers to the emulated Android device, not the PC that it works on). You must specify a "good" address to the Android device that refers to the machine on which the server executes.
So, the problem is not in using sockets.
You can simply connect to your server using this line, also try to disable your firewall if your server is running on your PC.
Socket server= new Socket("192.168.1.1", 4444); // Enter your PC/Server IP address in place of 192.168.1.1

Nodejs Express + Socket.io + client on C#

i just don't understand why simple socket.io part don't work.
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var bodyParser = require('body-parser');
var routes = require('./routes/index');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
http.listen(3000, function(){
console.log('listening on *:3000');
});
app.use(function(req, res, next) {
console.log("INIT");
console.log(req.headers['user-agent']);
console.log(req.ip);
next();
});
app.use('/', routes);
io.on('connection', function(socket){
console.log('a user connected');
socket.on('disconnect', function(){
console.log('user disconnected');
});
});
This is my cliend side code at C#. So when my nodejs server is online i don't get any errors from C#, so it's connecting, but i don't see it at node console.
And this must work, i get this example here - https://www.youtube.com/watch?v=nwV3MS6pryY
using System;
using System.Net.Sockets;
namespace TCPSocketConsole
{
class Program
{
static TcpClient mySocket = new TcpClient();
static void Main(string[] args)
{
mySocket.Connect("127.0.0.1", 3000);
Console.ReadLine();
}
}
}
So when i connect to http://localhost:3000 i don't get "a user connected" at my console.
You are listening for a socket.io connection on your server, but your client is just make a plain TCP connection. The two protocols on each end must be the same. socket.io is not a plain TCP connection.
You can either listen for a plain TCP connection on your node.js server (and thus invent your own protocol) or you can get a class for a socket.io connection in your C# client so your C# client can actually speak to a socket.io server properly.
socket.io is based on webSocket and webSocket has a whole protocol for establishing the initial connection (it starts with an HTTP connection that is then upgraded to a webSocket connection) and then both webSocket and socket.io have their own framing for how data is sent. Both ends of the connection must speak the same protocol.
In the socket.io docs you have an example of the client and server side. It seems your are not connecting from client side.

Categories

Resources