Named Pipes IPC: Python server, C# Client - c#

Title sums it up. There are plenty of examples around with a c# server and python client communicating back and forth.
I'd like to understand how I can instead create a python server and c# client for some interprocess communication.

I managed to find a solution. To begin, I'd first like to clarify some confusing terminology and obscure naming conventions used in dotnet core.
It appears that the NamedPipeServerStream and NamedPipeClientStream don't actually operate on named pipes but instead on unix domain sockets. This means that we must use sockets to communicate between processes rather than FIFO files.
Another frustration I find with dotnet core is that when creating a socket or connecting to one, the NamedPipeServerStream and NamedPipeClientStream classes will add "CoreFxPipe_" to the beginning of the socket name. See related question.
Python Server
#!/usr/bin/python3
import socket
import os
import struct
SOCK_PATH = "/tmp/CoreFxPipe_mySocket"
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
try:
os.remove(SOCK_PATH)
except OSError:
pass
sock.bind(SOCK_PATH)
sock.listen()
conn, addr = sock.accept()
with conn:
try:
while True:
amount_expected = struct.unpack('I', conn.recv(4))[0]
print("amount_expected :", amount_expected)
message = conn.recv(amount_expected)
print("Received message : ", message.decode())
# Send data
message_rev = message[::-1].decode()
print("Sent message (reversed) : ", message_rev)
conn.sendall(
struct.pack(
'I',
len(message_rev)
)
+ message_rev.encode('utf-8')
)
except (struct.error, KeyboardInterrupt) as e:
print(e)
finally:
print('closing socket')
C# Client
using System;
using System.IO;
using System.IO.Pipes;
using System.Text;
class PipeClient
{
static void Main(string[] args)
{
using (NamedPipeClientStream pipeClient =
new NamedPipeClientStream(".", "mySocket", PipeDirection.InOut))
{
// Connect to the pipe or wait until the pipe is available.
Console.WriteLine("Attempting to connect to pipe...");
pipeClient.Connect();
try
{
// Read user input and send that to the client process.
using (BinaryWriter _bw = new BinaryWriter(pipeClient))
using (BinaryReader _br = new BinaryReader(pipeClient))
{
while (true)
{
//sw.AutoFlush = true;
Console.Write("Enter text: ");
var str = Console.ReadLine();
var buf = Encoding.ASCII.GetBytes(str); // Get ASCII byte array
_bw.Write((uint)buf.Length); // Write string length
_bw.Write(buf); // Write string
Console.WriteLine("Wrote: \"{0}\"", str);
Console.WriteLine("Let's hear from the server now..");
var len = _br.ReadUInt32();
var temp = new string(_br.ReadChars((int)len));
Console.WriteLine("Received from client: {0}", temp);
}
}
}
// Catch the IOException that is raised if the pipe is broken
// or disconnected.
catch (IOException e)
{
Console.WriteLine("ERROR: {0}", e.Message);
}
}
Console.Write("Press Enter to continue...");
}
}
Sources:
https://abgoswam.wordpress.com/2017/07/13/named-pipes-c-python-net-core/
https://realpython.com/python-sockets/
https://unix.stackexchange.com/questions/75904/are-fifo-pipe-unix-domain-socket-the-same-thing-in-linux-kernel

Related

Parsing host:port expressions

What's the best and simplest way to parse an environment variable of the following possible forms: host[:port]
redis
redis:6379
10.0.0.72
10.0.0.72:6379
my.domain.name
my.domain.name:6379
The inputs are never prepended with a protocol.
The end goal is to parse out the host and port in order to create an object of type System.Net.IPEndPoint, possibly after using Dns.GetHostAddresses(host)[0] depending on whether there is an ip or a hostname supplied in the environment variable.
The purpose is helping dotnet core apps inside various docker containers discover each other according to values specified in their environment variables.
I'm hoping to make use of parsing utilities already available in the dotnet core libraries rather than roll my own parser.
new Uri("redis:6379") produces invalid results.
new Uri("https://redis:6379") produces a Uri object with correct host and port properties, but it seems ridiculous to me that it should be necessary to malform all the inputs by prepending "https://" just to get the Uri object to parse it correctly.
new Uri("https://redis") incorrectly sets the Port property as 443 and doesn't indicate that it wasn't supplied in the user input.
If it's possible to skip parsing steps and resolve straight to IPEndPoint with no in-between steps, that would be my preferred answer.
This is what I'm using at the moment, with error handling removed. Have you got something better?
IPEndPoint ParseGateway(string input) {
var parts = input.Split(':');
var host = parts[0];
var port = parts.Length > 1 ? int.Parse(parts[1]) : DEFAULT_GATEWAY_PORT;
var ip = Dns.GetHostAddresses(host)[0];
return new IPEndPoint(ip, port);
}
Use string method SubString as shown below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] inputs = {
"redis",
"redis:6379",
"10.0.0.72",
"10.0.0.72:6379",
"my.domain.name",
"my.domain.name:6379"
};
string address = "";
string port = "";
foreach (string input in inputs)
{
if (input.Contains(":"))
{
address = input.Substring(0, input.IndexOf(":"));
port = input.Substring(input.IndexOf(":") + 1);
}
else
{
address = input;
port = "";
}
Console.WriteLine("Address : '{0}'; Port : '{1}'", address, port);
}
Console.ReadLine();
}
}
}

C# socket hangs when receive in loop - python as socket server

I'm familiar with C#, and know some python. Recent days I'm learning the book Programming Python, 4th Edition and have run the very basic socket samples: echo-server.py and echo-client.py
They work well on my Windows, python 3.x.
python server:
from socket import *
myHost = 'localhost'
myPort = 50007
sockobj = socket(AF_INET, SOCK_STREAM)
sockobj.bind((myHost, myPort))
sockobj.listen(5)
while True:
connection, address = sockobj.accept()
print('Server connected by', address)
while True:
data = connection.recv(1024)
if not data: break
connection.send(b'Echo=>' + data)
connection.close()
Now I want to learn socket in C# too, so I wrote a C# .net framework 4.5 socket client, expecting to receive and show what echo-client.py does.
I got the C# demo from msdn and made some refactor to reduce code size.
public static void Main(string[] args)
{
string server = "localhost";
int port = 50007;
string request = "GET / HTTP/1.1\r\nHost: " + server +
"\r\nConnection: Close\r\n\r\n";
Byte[] sent = Encoding.ASCII.GetBytes(request);
Byte[] recv = new Byte[256];
IPHostEntry hostEntry = Dns.GetHostEntry(server);
IPEndPoint ipe = new IPEndPoint(hostEntry.AddressList[1], port);
Socket s =
new Socket(ipe.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
s.Connect(ipe);
s.Send(sent, sent.Length, 0);
int bytes = 0;
string page = "recived:\r\n";
//do
{
bytes = s.Receive(recv, recv.Length, 0);
page = page + Encoding.ASCII.GetString(recv, 0, bytes);
}
//while (bytes > 0);
Console.WriteLine(page);
Console.WriteLine("result");
Console.ReadKey();
}
My test steps:
If I set up a web site using local IIS, such as
http://localhost:801, then above code can show the homepage html
contents, this means my C# code is working.
Run echo-server.py, and change C# code's port to 50007, then run,
nothing output in console, and application does not exit, if I place a break point within the loop, I can see the loop has only run once. The python server did output some log saying C# is connecting.
Comment do while loop(as commented in code), this time the output is exactly same as echo-client.py(expected).
So I'm wondering what's wrong when I'm using do while loop?

Serial Port Request-Response communication using c#

I want to do serial port communication with a machine which uses RS232-USB ports.
I am using serial port class. I am very new to the concept. In my first Machine interfacing I only had to do the serialport.readLine( to get the readings from the machine and there was no need to send ACK /NAK). but for the new machine interface the document says following things:
The following is an example of the RA500 communication:
Computer :<05h 31h 0dh>
RA500 :1st line of information
Computer :<06h 0dh>
RA500 :2nd line of information
Computer :<06h 0dh>
RA500 :”EOF”<0dh>
What i understood from this is i have to write to comport before reading from it. this is what i am doing in my code:
ACK = "06 0d"; NAK = "15 0d"; str = "05 31 0d";
while (count <= 5)
{
rx = ComPortDataReceived(str);
if (!string.IsNullOrEmpty(rx))
{
str = ACK;
returnReading += rx;
}
else if (string.IsNullOrEmpty(rx)) str = NAK;
count++;
}
private string ComPortDataReceived(string str)
{
string Rx = string.Empty;
string exceptionMessage = string.Empty;
try
{
byte[] bytes = str.Split(' ').Select(s => Convert.ToByte(s, 16)).ToArray();
comPort.Write(bytes, 0, bytes.Length);
Rx = comPort.ReadExisting();
PEHRsLibrary.writeTextFile(DateTime.Now + " RxString :" + Rx);
return Rx;
}
catch(Exception e){}
when i use this code i am receiving empty strings as responce. but if i use comPort.ReadExisting() only without using comPort.Write i am receving a string with all the readings but the probblem is it only gives one line of information and dosnt give 2nd or 3rd line readings.
when i try using comPort.ReadLine() after Write() I am getting Timeout exception.
i dont know what i am doing wrong in this case. I am writing ACk after receving 1st line but not receving 2nd line. Next thing i am gonna try is read() as byte and then convert it to string instead of using ReadExisting(). Any other way i can do this?

named pipes between winform (C#) and python

I am working on a window form app (C#) that should kick an external process and display some results and/or error messages from the exe in the form app.
I cannot seem to be able to form a named pipe connection between the form app and external process (exe) made in python. The exe fires up and works fine but it does not seem to hold the named pipe connection. So, I am not able to get any messages as such from the exe.
The exe is made with pyinstaller and named pipe connection seems to work pretty fine when paired with a window console app i.e. I could get messages back from the exe to a console app.
Consolse App
The script below can get return messages from the exe on to console.
namespace pipeConsoleApp
{
class Program
{
static void Main(string[] args)
{
NamedPipeClientStream pipeClient = new NamedPipeClientStream("teropipe");
Console.Write("Attempting to connect to the pipe...");
System.Diagnostics.Process.Start(#"my\path\to\external\app\tempp.exe");
pipeClient.Connect();
Console.WriteLine("Connected to the pipe");
Console.WriteLine("There are currently {0} pipe server instances open.", pipeClient.NumberOfServerInstances);
StreamWriter writer = new StreamWriter(pipeClient);
StreamReader reader = new StreamReader(pipeClient);
string temp;
while ((temp = reader.ReadLine()) != null)
{
Console.WriteLine("Received from server: {0}", temp);
}
Console.Write("Press Enter to continue..");
Console.ReadLine();
}
}
But when I tried a similar thing on window form app I am not able to get anything from the python server
Form App
Although I have used a similar approach for the form app somehow no messages are being returned. In fact, it looks like the named piped connection isn't being held open for the form to communicate.
namespace pipeDemoForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void okayButton_Click(object sender, EventArgs e)
{
NamedPipeClientStream pipeClient = new NamedPipeClientStream("teropipe");
//MessageBox.Show("attempting to connect");
System.Diagnostics.Process.Start(#"my\path\to\external\app\tempp.exe");
pipeClient.Connect();
string numb = pipeClient.NumberOfServerInstances.ToString();
MessageBox.Show("There are currently {0} pipe server instances open", numb);
if (pipeClient.IsConnected)
{
MessageBox.Show("There are currently {0} pipe server instances open", pipeClient.NumberOfServerInstances.ToString());
}
}
}
}
Python Script - tempp.exe
The following is the python script, which I have packaged into a onefile exe with pyinstaller.
import win32pipe
import win32file
def process():
pipe_handle = win32pipe.CreateNamedPipe(r'\\.\pipe\teropipe',
win32pipe.PIPE_ACCESS_DUPLEX,
win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_WAIT,
1,65536,65536,300,None)
win32pipe.ConnectNamedPipe(pipe_handle, None)
# business logic
..................
#write some output to the form app
win32file.WriteFile(pipe_handle,"some string return from above")

Connect an C# application thats running sockets using JAVASCRIPT

Hey i was wondering if you could help me
I'm creating an android application in html5 and java script.
There are a server that is created on c# that is listing connection.
I can connect the 2 apps together but get i can get the c# app to reply to my android application using javascript.
here is my server code
public void Listeners()
{
Socket socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected)
{
nr_connections = nr_connections + 1;
nr_qry = nr_qry + 1;
SetText("");
SetText("New Connection.");
NetworkStream networkStream = new NetworkStream(socketForClient);
StreamWriter streamWriter = new StreamWriter(networkStream);
StreamReader streamReader = new StreamReader(networkStream);
streamWriter.Flush();
string GettheString = streamReader.ReadLine();
if (GettheString == "server_status")
{
SetText("Checking Server Status.");
streamWriter.WriteLine("Online");
streamWriter.Close();
streamReader.Close();
networkStream.Close();
}
}
socketForClient.Close();
SetText("Connection Closed...");
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
nr_connections = nr_connections - 1;
}
and my javascript code
function connect ()
{
try
{
var connection = new WebSocket('ws://105.237.125.247:8');
connection.onopen = function ()
{
connection.send('server_status');
};
connection.onmessage = function (event) {
alert(event.data);
}
}
catch(Exeption)
{
alert("Check Connection");
}
}
Im getting data from the android app but can send back to the javascript file
Web-sockets is a protocol that sits on top of a regular transport (such as a socket); basically, you need a web-socket library. If you are using recent versions of Windows, then much of this is baked into HTTP.SYS, and available via HttpListnener (in particular, AcceptWebSocketAsync on a context). However, alternative web-socket libraries are available, or can be written from scratch if you so choose.

Categories