├── Makefile
├── README.md
├── clients
├── client.c
├── client.h
└── utils.c
├── screenshots
├── send_signal_1.png
├── send_signal_2.png
├── send_signal_3.png
└── signals.jpg
└── servers
├── server.c
├── server.h
└── utils.c
/Makefile:
--------------------------------------------------------------------------------
1 | NAME = client
2 | NAME2 = server
3 |
4 | FUNCTIONS = ./clients/client \
5 | ./clients/utils
6 |
7 | FUNC = ./servers/server \
8 | ./servers/utils
9 |
10 | FLAGS = -Wall -Wextra -Werror
11 |
12 | SRC = $(addsuffix .c, $(FUNCTIONS))
13 | EXCH = $(addsuffix .o, $(FUNCTIONS))
14 |
15 | SRC2 = $(addsuffix .c, $(FUNC))
16 | EXCH2 = $(addsuffix .o, $(FUNC))
17 |
18 | all: $(NAME) $(NAME2)
19 |
20 | $(NAME): $(EXCH)
21 | gcc $(FLAGS) $(EXCH) -o $(NAME)
22 |
23 | $(NAME2): $(EXCH2)
24 | gcc $(FLAGS) $(EXCH2) -o $(NAME2)
25 |
26 | %.o: %.c
27 | gcc $(FLAGS) -o $@ -c $<
28 |
29 | clean:
30 | /bin/rm -f ./clients/*.o
31 | /bin/rm -f ./servers/*.o
32 |
33 | fclean: clean
34 | /bin/rm -f $(NAME) $(NAME2)
35 |
36 | re: fclean all
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | ________________________________________________________________
4 |
5 | ####
"Это реально ненормальное программирование! :)"
####
6 | ________________________________________________________________
7 |
8 |
9 | ### Цель проекта:
10 | Реализовать связь между двумя процессами Client и Server посредством сигналов в С, по стандарту 98 года.
11 | В виде связи выступает передача строки от одного процесса к другому.
12 |
13 | ### Реализация:
14 | Текущий процесс приостанавливается (pause) и в нем работает обработчик сигнала, который срабатывает при получении сигнала (func my_handler).
15 | Будем отправлять строку посредством сигналов sigusr1 и sigusr2. Один символ - отправка 8 сигналов.
16 | Каждый сигнал будет отправлен в виде 0 или 1, символ будет переведен в ASCII код и далее в двоичную систему счисления.
17 | Использовать будем сигналы sigusr1, означающий 1, и sigusr2, означающий 0.
18 | Двоичная система счисления имеет 8 байт, следовательно server будет знать, что каждые 8 сигналов - это один символ. В таком случае нужно обратить внимание, что некоторые алгоритмы конвертации dec2bin отсеивают ведущие нули. Если запрос придет меньше 8 сигналов - сервер не обработает его.
19 | Как только сервер принимает запрос (т.е один символ), он его переводит bin2dec и выводит на экран. Таким образом отсылается и выводится вся строка.
20 |
21 | ### Стек технологий:
22 | * С
23 | * Signals
24 |
25 | ________________________________________________________________
26 |
27 |
28 |
29 | Screenshots
30 |
31 | ________________________________________________________________
32 |
33 | 
34 | 
35 | 
36 | ________________________________________________________________
37 |
38 |
39 |
40 |
41 | Полезная информация и ссылки
42 |
43 | Обработка сигналов занимает некоторое время, и если вы посылаете слишком много за один раз, некоторые из них могут быть проигнорированы. Именно поэтому я использую usleep.
44 | Printf нельзя вызывать внутри сигнала. Именно из-за printf не мог понять почему server не принимал сигнал. Советую не использовать его в момент написания проекта или его тестирования.
45 | Подробнее о SIGUSR1 и SIGUSR2
47 | Передача файлов сигналами
48 | Как узнать завершился ли процесс-потомок?
49 | Список разрешенных функций внутри обработчика сигнала
50 |
51 |
52 |
53 |
54 |
55 |
56 | bin2dec и dec2bin
57 |
58 | ```C
59 | int bin2dec(int n)
60 | {
61 | int num;
62 | int dec_value;
63 | int base;
64 | int temp;
65 | int last_digit;
66 |
67 | num = n;
68 | base = 1;
69 | dec_value = 0;
70 | temp = num;
71 | while (temp)
72 | {
73 | last_digit = temp % 10;
74 | temp = temp / 10;
75 | dec_value += last_digit * base;
76 | base = base * 2;
77 | }
78 | return dec_value;
79 | }
80 |
81 | int dec2bin(int server_pid, int num)
82 | {
83 | int bin = 0;
84 | int k = 1;
85 | int i = 0;
86 |
87 | while (num)
88 | {
89 | bin += (num % 2) * k;
90 | k *= 10;
91 | num /= 2;
92 | i++;
93 | }
94 | return bin;
95 | }
96 | ```
97 |
98 |
99 |
100 | ### Если я помог как-то вам, то буду благодарен за звездочку :)
101 |
102 |
--------------------------------------------------------------------------------
/clients/client.c:
--------------------------------------------------------------------------------
1 | // by atomatoe
2 |
3 | #include "client.h"
4 |
5 | void decimal_conversion(char ascii, int power, int pid)
6 | {
7 | if (power > 0)
8 | decimal_conversion(ascii / 2, power - 1, pid);
9 | if ((ascii % 2) == 1)
10 | {
11 | if (kill(pid, SIGUSR1) == -1)
12 | {
13 | ft_putstr("Error signal!\n");
14 | exit(0);
15 | }
16 | }
17 | else
18 | {
19 | if (kill(pid, SIGUSR2) == -1)
20 | {
21 | ft_putstr("Error signal!\n");
22 | exit(0);
23 | }
24 | }
25 | usleep(100);
26 | }
27 |
28 | int send_message(int server_pid, char *msg)
29 | {
30 | int i;
31 |
32 | i = 0;
33 | while (msg[i] != '\0')
34 | {
35 | decimal_conversion(msg[i], 7, server_pid);
36 | i++;
37 | }
38 | return (0);
39 | }
40 |
41 | void my_handler(int signum, siginfo_t *siginfo, void *unused)
42 | {
43 | (void)unused;
44 | (void)siginfo;
45 | (void)signum;
46 | ft_putstr("Signal received\n");
47 | }
48 |
49 | int main(int argc, char **argv)
50 | {
51 | struct sigaction catch;
52 |
53 | catch.sa_flags = SA_SIGINFO;
54 | catch.sa_sigaction = my_handler;
55 | if ((sigaction(SIGUSR2, &catch, 0)) == -1)
56 | error("Error sigaction\n");
57 | if (argc == 3)
58 | send_message(atoi(argv[1]), argv[2]);
59 | else
60 | error("Error arguments\n");
61 | while (1)
62 | pause();
63 | return (0);
64 | }
65 |
--------------------------------------------------------------------------------
/clients/client.h:
--------------------------------------------------------------------------------
1 | // by atomatoe
2 |
3 | #ifndef CLIENT_H
4 | # define CLIENT_H
5 |
6 | # include
7 | # include
8 | # include
9 |
10 | void ft_putstr(char *str);
11 | void error(char *str);
12 | void decimal_conversion(char ascii, int power, int pid);
13 | int send_message(int server_pid, char *msg);
14 | void my_handler(int signum, siginfo_t *siginfo, void *unused);
15 |
16 | #endif
--------------------------------------------------------------------------------
/clients/utils.c:
--------------------------------------------------------------------------------
1 | // by atomatoe
2 |
3 | #include "client.h"
4 |
5 | void ft_putstr(char *str)
6 | {
7 | int i;
8 |
9 | i = 0;
10 | while (str[i])
11 | {
12 | write(1, &str[i], 1);
13 | i++;
14 | }
15 | }
16 |
17 | void error(char *str)
18 | {
19 | ft_putstr(str);
20 | exit(0);
21 | }
22 |
--------------------------------------------------------------------------------
/screenshots/send_signal_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atomatoe/minitalk/d6035c26ee804bcbb67eabeca606f6cba804c0f1/screenshots/send_signal_1.png
--------------------------------------------------------------------------------
/screenshots/send_signal_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atomatoe/minitalk/d6035c26ee804bcbb67eabeca606f6cba804c0f1/screenshots/send_signal_2.png
--------------------------------------------------------------------------------
/screenshots/send_signal_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atomatoe/minitalk/d6035c26ee804bcbb67eabeca606f6cba804c0f1/screenshots/send_signal_3.png
--------------------------------------------------------------------------------
/screenshots/signals.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atomatoe/minitalk/d6035c26ee804bcbb67eabeca606f6cba804c0f1/screenshots/signals.jpg
--------------------------------------------------------------------------------
/servers/server.c:
--------------------------------------------------------------------------------
1 | // by atomatoe
2 |
3 | #include "server.h"
4 |
5 | void sig_to_str(int bin)
6 | {
7 | char c;
8 | int i;
9 |
10 | i = 0;
11 | c = '\0';
12 | c += (bin << i++);
13 | if (i > 7)
14 | {
15 | if (c == '\0')
16 | ft_putchar('\n');
17 | else
18 | ft_putchar(c);
19 | c = 0;
20 | i = 0;
21 | }
22 | }
23 |
24 | void my_handler(int signum, siginfo_t *siginfo, void *unused)
25 | {
26 | static int ascii = 0;
27 | static int power = 0;
28 |
29 | (void)unused;
30 | if (signum == SIGUSR1)
31 | ascii += 1 << (7 - power);
32 | power += 1;
33 | if (power == 8)
34 | {
35 | ft_putchar(ascii);
36 | power = 0;
37 | ascii = 0;
38 | if (kill(siginfo->si_pid, SIGUSR2) == -1)
39 | error("Error signal\n");
40 | }
41 | }
42 |
43 | int main(int argc, char **argv)
44 | {
45 | struct sigaction catch;
46 |
47 | (void)argv;
48 | if (argc != 1)
49 | error("Error arguments\n");
50 | write(1, "Server started!\nPID: ", 21);
51 | ft_putnbr(getpid());
52 | write(1, "\n", 1);
53 | catch.sa_flags = SA_SIGINFO;
54 | catch.sa_sigaction = my_handler;
55 | if ((sigaction(SIGUSR1, &catch, 0)) == -1)
56 | error("Error sigaction\n");
57 | if ((sigaction(SIGUSR2, &catch, 0)) == -1)
58 | error("Error sigaction\n");
59 | while (1)
60 | pause();
61 | return (0);
62 | }
63 |
--------------------------------------------------------------------------------
/servers/server.h:
--------------------------------------------------------------------------------
1 | // by atomatoe
2 |
3 | #ifndef SERVER_H
4 | # define SERVER_H
5 |
6 | # include
7 | # include
8 | # include
9 |
10 | void ft_putstr(char *str);
11 | void error(char *str);
12 | void ft_putchar(char c);
13 | void ft_putnbr(int n);
14 | void sig_to_str(int bin);
15 | void my_handler(int signum, siginfo_t *siginfo, void *unused);
16 |
17 | #endif
--------------------------------------------------------------------------------
/servers/utils.c:
--------------------------------------------------------------------------------
1 | // by atomatoe
2 |
3 | #include "server.h"
4 |
5 | void ft_putstr(char *str)
6 | {
7 | int i;
8 |
9 | i = 0;
10 | while (str[i])
11 | {
12 | write(1, &str[i], 1);
13 | i++;
14 | }
15 | }
16 |
17 | void error(char *str)
18 | {
19 | ft_putstr(str);
20 | exit(0);
21 | }
22 |
23 | void ft_putchar(char c)
24 | {
25 | write(1, &c, 1);
26 | }
27 |
28 | void ft_putnbr(int n)
29 | {
30 | if (n < 10)
31 | {
32 | ft_putchar(n + '0');
33 | return ;
34 | }
35 | ft_putnbr(n / 10);
36 | ft_putchar((n % 10) + '0');
37 | }
38 |
--------------------------------------------------------------------------------