-
Notifications
You must be signed in to change notification settings - Fork 0
2. Bonus
Por defecto, si desglosas cada caracter en bits
con los operadores de bits
, puede soportar Unicode
.
Recordatorio:
- Operadores de bits:
&
,|
,^
,~
,<<
y>>
Para recoger un bit
de X pos
de un caracter
, se usa:
(c >> bit) & 1 // `bit` es una variable que deberias inicializar como 8
Para cambiar un bit
de X pos
en un caracter
, se usa:
ch |= (1 << bit); // `bit` es una variable que deberias inicializar como 7
Uso de sigaction
Hasta ahora, he usado
signal
para detectar una señal, pero tambien existesigaction
.
Sigaction
/*
* sig => Numero de señal
* act => Estructura sigaction (Que contiene informacion bastante util)
* oact => Estructura opcional donde se almacenara la accion
*/
int sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact);
En la estructura act hay almacenada si_pid
que contiene el PID
del que ha mandado la señal.
- En server, cambiaremos
signal
porsigaction
, asi que habra que crear unaestructura
int main(void)
{
struct sigaction s_sig; //Esta es la estructura que vamos a necesitar
ft_printf("PID: %i\n", getpid());
s_sig.sa_sigaction = ft_print_sig; //Le pasamos la funcion que queremos llamar cuando se detecte una señal
s_sig.sa_flags = SA_SIGINFO; //SA_INFO comunica con una estructura que detecta el PID del cliente
sigaction(SIGUSR1, &s_sig, NULL); //LLamamos a sigaction para que detecte SIGUSR1 & SIGUSR2 + la estructura
sigaction(SIGUSR2, &s_sig, NULL);
while (1)
pause();
return (0);
}
- Modificamos la funcion de reconstruir bits => caracter.
Para que envie una señal cada vez que se recibaSIGUSR1
oSIGUSR2
El
PID
esta almacenado ensi_pid
static void ft_print_sig(int sig, siginfo_t *t_sig_info, void *oact)
{
static char ch;
static int bit = 7;
(void)oact;
if (bit == 7)
ch = 0;
if (sig == SIGUSR2)
ch |= (1 << bit);
kill(t_sig_info->si_pid, SIGUSR2); //Enviamos SIGUSR2 al recibir cualquier señal al cliente
bit--;
if (bit == -1)
{
ft_printf("%c", ch);
if (!ch)
kill(t_sig_info->si_pid, SIGUSR1); //Cuando llegamos al final del mensaje, enviamos SIGUSR1.
bit = 7;
}
}
Mandamos
'\0'
desdeclient
una vez lleguemos al final.
Elserver
sabe que el mensaje ha terminado, si detecta este caracter.
- Desde el cliente, mandar
'\0'
al final del mensaje
Aparte, podemos detectar cuando no hay nada en el mensaje y mostrar un error si ocurre.
static int ft_send_str(char *mess, int pid)
{
size_t i;
i = 0;
if (!mess || !ft_strllen(mess)) //Detecta si no hay mensaje o si no hay longitud en el mensaje
{
ft_printf("Nothing to send\n");
exit(1);
}
while (mess[i])
{
if (!ft_send_bits(mess[i], pid))
return (0);
usleep(50);
i++;
}
ft_send_bits('\0', pid);
return (1);
}
- Hacer que client tambien este pendiente de si le mandan una señal
Usamos
signal
para detectar señales, no es necesario usarsigaction
.
int main(int argc, char **args)
{
int pid;
if (argc != 3)
{
ft_printf("\033[1;31mWrong number of arguments!\n");
ft_printf("\033[1;33mRun like these:\n%s <PID> <Message>\n", args[0]);
exit(1);
}
if (!ft_is_all_num(args[1]))
{
ft_printf("\033[1;31mPID is invalid!\n");
exit(1);
}
pid = ft_atoi(args[1]);
signal(SIGUSR1, ft_confirm); //Funcion que llamara al detectar esta señal
signal(SIGUSR2, ft_confirm);
if (!ft_send_str(args[2], pid))
{
ft_printf("\033[1;31mWrong PID\n");
exit(1);
}
while (1)
pause();
return (0);
}
Hay que llamar a
signal
antes de enviar cualquier señal.
- Crear una pequeña funcion para
signal
static void ft_confirm(int sig)
{
static size_t bits;
if (sig == SIGUSR2)
{
bits++;
usleep(50); //Añadimos una pequeña pausa para que no se pierdan algunas señales
}
else if (sig == SIGUSR1)
{
bits -= 8; //Le resto el caracter '\0', porque no quiero que muestre que ha enviado este caracter.
ft_printf("Sended %u bits\n", bits);
exit(0);
}
}