C/Visual C - El printf de un thread interfiere en un scanf

   
Vista:
Imágen de perfil de Alejandro

El printf de un thread interfiere en un scanf

Publicado por Alejandro (12 intervenciones) el 24/10/2014 04:08:40
Hola que tal comunidad. Veran, tengo un thread que acepta conexiones mediante un socket. En el thread voy impriendo cada vez que se conecta un nuevo cliente, y en la funcion main tengo un scanf para mandarle mensajes a dichos clientes. El problema radica en que, el printf del thread interfiere en el scanf del main, algo asi:

1
scanf del main> DATOSDELTHREAD

Pero yo quisiera que los datos del thread me los mostrar de la siguiente manera:

1
2
DATOSDELTHREAD
scanf del main>
No se si de la manera que lo quiero hacer sea posible, ya que en la web no he encontrado mucho informacion al respecto.

Este es mi codigo:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h> 
#include <pthread.h> 
 
#define PORT 3550
#define BACKLOG 1
int fd2[30], fd;
struct sockaddr_in server, client;
char * control = "OK";
int x = 0;
void *connection_handler(void* data) {
    int sin_size = (int)data;
    sin_size = sizeof(struct sockaddr_in);
    while(control == "OK") {
        if((fd2[x] = accept(fd, (struct sockaddr *)&client, &sin_size)) < 0) {
            printf("Error en accept()\n");
            exit(-1);
         }
        printf("Cliente No: %d\n", x);
        fflush(stdout);
         x++;
    }
    pthread_exit(NULL);
}
 
int main() {
    if((fd=socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        printf("Error en socket()\n");
        exit(-1);
    }
 
    int yes = 1;
    if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) {
        printf("Error en setsockopt()\n");
        exit(-1);
    }
 
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = INADDR_ANY;
 
    bzero(&(server.sin_zero), 8);
    if(bind(fd,(struct sockaddr*)&server,sizeof(server)) < 0) {
        printf("Error en bind()\n");
        exit(-1);
    }
 
    if(listen(fd,BACKLOG) == -1) {
        printf("Error en listen()\n");
        exit(-1);
    }
 
    pthread_t thread_id;
    int rc;
    int sin_size;
    rc = pthread_create(&thread_id, NULL, connection_handler, (void *)sin_size);
    if(rc) {
        printf("Error en pthread()\n");
        return 1;
    }
 
    while(1) {
        char escribe[512];
        int respuesta;
        printf("Mensaje para el cliente No: ");
        fflush(stdout);
        scanf("%d", &respuesta);
        printf("-> ");
        fflush(stdout);
        scanf("%s", escribe);
 
        send(fd2[respuesta], escribe, strlen(escribe), 0);
        if(strcmp(escribe, "exit") == 0) {
             break;
        }
    }
    int i;
    for(i=0;i<=x;i++) {
        close(fd2[i]);
    }
    control = "NOT";
    close(fd);
 
    return 0;
}

Gracias.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

El printf de un thread interfiere en un scanf

Publicado por Tom (481 intervenciones) el 24/10/2014 08:07:49
Supongo que lo que quieres decir es que la salida del printf aparece en el terminal mientras estás realizando un scanf.
Supongo también que sabes que no te afecta al scanf, es decir, no va a leer nada que no hayas escrito.

Pues la solución más obvia (quizás no la mejor) es sincronizar los threads. Y sobre eso hay muchísima literatura por la red.

https://www.google.es/search?q=sincronizaci%C3%B3n+posix+threads&oq=sincronizaci%C3%B3n+posix+threads
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

El printf de un thread interfiere en un scanf

Publicado por Tom (481 intervenciones) el 24/10/2014 12:38:01
ufff no solo eso, ya veo por dónde vas ...
Puedes usar ncurses que te permitiría definir varias áreas en la consola (una superior por ejemplo para la salida del thread, y una inferior para los scanf) o liarte e intentar hacerlo con las secuencias de escape del terminal:

https://code.google.com/p/conemu-maximus5/wiki/AnsiEscapeCodes
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Alejandro

El printf de un thread interfiere en un scanf

Publicado por Alejandro (12 intervenciones) el 24/10/2014 19:14:05
Gracias, lo intentare con ncurses, se ve mas facil de esa manera. Ya lo habia intentado con los escapes de la terminal, pero como dices tu, es un gran lio hacerlo. ¡Agradezco mucho tu ayuda! :D
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Alejandro

El printf de un thread interfiere en un scanf

Publicado por Alejandro (12 intervenciones) el 25/10/2014 00:07:40
Al ultimo opte por usar los escapes de la terminal, ya que contaba con poco timepo para aprender a usar ncurses.
A quien le pueda ser util, esto fue lo que hice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void *connection_handler(void* data) {
    int sin_size = (int)data;
    sin_size = sizeof(struct sockaddr_in);
    while(control == "OK") {
        if((fd2[x] = accept(fd, (struct sockaddr *)&client, &sin_size)) < 0) {
            printf("Error en accept()\n");
            exit(-1);
        }
        printf("\x1B[s");   //Creamos un nuevo cursor
        fflush(stdout);
        printf("\x1B[F");  //Movemos el cursor una linea arriba
        fflush(stdout);
        printf("Cliente No: %d\n", x);  //Imprimimos en dicha linea
        fflush(stdout);
        printf("\x1B[J\n");  //Damos un salto de linea y borramos todo lo que se encuentra en la parte inferior (esto se hace para evitar empalmar datos) 
        fflush(stdout);
        printf("\x1B[u");  //Cerramos el cursor y vuelve a su posicion original (es decir, con el scanf)
        fflush(stdout);
        printf("\rMensaje para el cliente No: ");   //Como borramos todo lo de la parte inferior, volvemos a pedir el destino del mensaje con retorno de carro (\r) 
        fflush(stdout);
        x++;
     }
     pthread_exit(NULL);
 
}
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar