Simple Client+Server invoked with signals

dotnet-10 makes prototyping and playing around very easy (using dotnet run single-file.cs)

In this example:

  • using just stdin and stdout with signal
  • server run, then waits for a signal SIGUSR1 = 10
  • on signal
    • runs client
    • writes Hello,World
    • reads stdout and echos
  • client
    • read stdin and echos to stdout with a prefix

Server

#!/bin/env -S dotnet run
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;

// $ man signal
[DllImport("libc")]
static extern void signal(int signum, Action handler);

static void HandleSIGUSR1()
{
    Console.WriteLine("SIGUSR1 received!");
    var proc = Process.Start(
        new ProcessStartInfo("./client.cs")
        {
            RedirectStandardInput = true,
            RedirectStandardOutput = true,
        });
    Thread.Sleep(100);
    if (proc != null)
    {
        Console.WriteLine($"Started: {proc.Id}.. waiting");
        var task = Task.Run( ()=>
        {
                proc.StandardInput.WriteLine("Hello");
                Thread.Sleep(100);
                proc.StandardInput.WriteLine("World");
                Thread.Sleep(100);
                proc.StandardInput.Close();
        });

        while (proc.StandardOutput.ReadLine() is {} outp)
        {
            Console.WriteLine($"| {outp}");
        }
    }

    Console.WriteLine("Closed");
    Console.WriteLine();
}

Console.WriteLine($"server.cs  --  PID={Environment.ProcessId}");
Console.WriteLine("");
Console.WriteLine(
        """
        Waiting for SIGUSR1...
        To send the signal, run:
        $ kill -SIGUSR1 `pidof server`
        """);

signal(/* SIGUSR1 */ 10, HandleSIGUSR1);
while (true)
{
    Thread.Sleep(200);
}

Client


#!/bin/env -S dotnet run
Console.WriteLine($">client.cs -- PID={Environment.ProcessId}");
Console.WriteLine(">Another");
while(Console.ReadLine() is {} line)
{
    Console.WriteLine($"    <-> {line}");
}
Console.WriteLine(">bye");

Result

screenshot