- C 73.6%
- Makefile 26.4%
| bonus | ||
| ext/ft | ||
| .gitignore | ||
| client.c | ||
| client.h | ||
| client.mk | ||
| error.c | ||
| error.h | ||
| Makefile | ||
| minitalk.h | ||
| README.md | ||
| server.c | ||
| server.h | ||
| server.mk | ||
| template.mk | ||
This project has been created as part of the 42 curriculum by jmaxwell.
minitalk
description
implementing client server communication exclusively through unix signals
bonus
all bonuses were implemented.
acknowledgement signal
over time delay estimation (back and forth communication)
unicode characters
this is achieved at no additional cost as a byproduct of the method in use
purpose
the following serves as a barebones conceptualisation of client server communication ; by virtue of the constraints laid out in the subject, it also aims to grow our familiarity with the linux api through the use of signals.
implementation
in either of the cases detailed below, the same algorithm applies. the client, to which a payload is assigned, will, for each byte, consider each bit in sequence, sending one of two reserved signals (SIGUSR1 and SIGUSR2) according to the value of the current bit. depending on the signal caught by the server, the value of the bit is derived, where SIGUSR2 translates to a 0, and SIGUSR1, conversely, maps to a 1. for legibility purposes, these are referenced behind macros common to both parties (client and server), namely SIG_BIT and SIG_SKIP. we then either estimate the processing time of the other party (client awaits server, usually), as is the case in the naive implementation ; alternatively, each party sends an acknowledgment signal with each bit processed, back and forth until the whole message was sent.
foundation
the base (or naive) implementation does not rely on any acknowledgement signal from the server back to the client, and as such is prone to desynchronisation.
by estimating a minimum processing delay per bit, depending on the resources available to a client server instance pair (i.e. under heavy load), it is possible for a signal not to be delivered in time within a byte, which will offset the rest of the message by one bit and will result in garbage looking output.
a potential improvement could be to implement a byte acknowledgement signal on top of that sent for each bit, which would greatly reduce the likelyhood of an offset arising. indeed, unless all bits of the current byte were somehow unable to be delivered (in which case something other than desynchronisation has gone very wrong), when SIG_BYTE would be sent by the client to indicate that it has reached the end of the byte it was sending, the server would check its own local position within the byte, and if it is not at the end (ergo the beginning, as the index is stored modulo 8) that would indicate a loss somewhere within said byte. communication would then begin anew, in an attempt to transmit the same byte, fully this time.
such a safety mechanism being outside the scope of this project, i have not implemented it. yet.
bonus
in contrast to this, the bonus implementation relies on back and forth signal communication to achieve informed transmission, which in effect amounts to real time adjustment of the delay between each bit, rather than a rough estimation, which as laid out above, was prone to issues of desynchronisation and deadlocking, being susceptible to system load.
this version of minitalk is as close to immune to those issues as can be, with the same potential improvement being the only safety mechanism keeping it from practical perfection.
instructions
usage
the server ought be launched first, as its pid must have been attributed in order for any subsequent client instances to reference the host to which their payload will be sent.
./server
./client <server pid> <payload>
any payload assigned for a client to communicate to a server (targeted through the pid argument) will be echoed to the server's standard output in real time, as the payload is decomposed character by character, and sent bit by bit.
for testing purposes, one may consider invoquing a client carrying its payload according to the following command :
./client <server pid> $(head -n 1000 /dev/random | base64)
compilation
you may make, optionally specifying bonus.
the latter should enable much more efficient communication, as each signal
(ergo each bit) will await acknowledgement from the other end before carrying
on, as opposed to sleeping for a set duration.
this approach, that of the bonus, is both faster (by virtue of not wasting
quite as much time sleeping), and safer ;
as the arbitrary delay chosen in the non-bonus implementation is really only a
rough estimate of a minimal safety delay below which signals may be lost, for
instance under heavy cpu load.
make
binaries will be found at the project root.
make bonus
binaries will be found under bonus/.
said binaries include a client as well as a server.
resources
peers
tpotier
clarifying the purpose and caveats of sigaction
@not_claire
motivating me as well as warning me of eventual edge cases to consider (resetting on a new client pid for instance)
@malou
giving me directions as to what to research, and pointing out the final flaw
that had been allowing a race condition to randomly deadlock both parties ;
std::pause is not atomic...
lbolea
lbolea actually first pointed this out but i had understood that as to mean that a usleep before the pause would prevent the deadlock by giving headway, which it doesn't.
meaba
debugging and testing
kim my
helping me debug, test and realise which delays were actually required, my bonuses are functional thanks to them
documentation
background
i had never used unix signals before, let alone in c, so this was new. most of the effort was therefore spent looking up how to interface with sigaction and signal, as program architecture was relatively straight forward.
-
do not mirror this repo or host a fork of it on github for reasons outlined here, none of the code present here should be hosted on github in any way, whether partially or totally. ↩︎
-
the following is certified human labour the entirety of the code in this repo was designed, implemented and tested entirely by humans, without the involvement of llms at any stage of the process, besides during research in the form of unprompted search engine summaries. whenever possible, its use was avoided. any trace of ai involvement is either coincidental or accidental, and beyond my knowledge. ↩︎
-
due to the policy currently in place at time of redaction, the unexplictly authorised publication of 42 subjects to individuals who may potentially lack the privilege to access them otherwise remains prohibited. as such, i will not be saving a copy of the relevant subject in this repository, however much i wish i could. ↩︎
