Bonjour,
je désire porter une application WinXP vers Linux Ubuntu.
Pour les besoins du projet, j’utilise des sockets pour échanger diverses données entre plusieus processus.
Je souhaite configurer mes sockets comme non bloquantes.
Mon processus principal (core) créé une socket d’écoute « listen_socket[SockID] ](cf ci dessous).
Les autres process viennent se connecter au process principal via une socket de service.
Voici mon problème :
Sous WinXP, j’arrive bien à configurer mes sockets comme non bloquantes, mais sous Linux, ça ne fonctionne pas comme prévu.
Mon processus principal reste bloqué lors d’un read sur la socket de service jusqu’à ce qu’il reçoive un message de l’un des processus clients.
C’est très embêtant car le processus core doit être apte à poursuivre son job malgré qu’aucune donnée ne lui ai été envoyée par un des clients.
Je poste ci dessous un extrait de chacune des fonctions qui crée:
- La socket d’écoute pour le processus principal.
L'option SockID me permet ensuite de pouvoir ré accéder à plusieurs sockets créées (stockage du descripteur retourné dans l'un ou l'autre des 2 tableaux définis comme globaux et dont la déclaration ne figure pas ici.)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 int Create_ListenSocket(u_short nPort, int SockID) { if (SockID > ListenAllocated-1) { fprintf(stderr, "\nUnable to create listening socket! Please Allocate first with Alloc_ClientSocks(int nb);\n"); return (0); } struct sockaddr_in my_addr; int state_flags = 0; listen_socket[SockID] = socket(AF_INET, SOCK_STREAM, 0); if (listen_socket[SockID] == -1) { fprintf(stderr, "\nError while creating Listen socket[%d], error code: %d\n", SockID, errno); printf("Error: %d\n", errno); return (0); } else printf("Listen-socket() sockfd is OK...\n"); /* host byte order */ my_addr.sin_family = AF_INET; /* short, network byte order */ my_addr.sin_port = htons(nPort); my_addr.sin_addr.s_addr = INADDR_ANY; /* zero the rest of the struct */ memset(&(my_addr.sin_zero), 0, 8); if(bind(listen_socket[SockID], (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { perror("bind() error on listen socket!\n"); printf("Error: %d\n", errno); return (0); } else printf("bind() is OK...\n"); // setup listen_socket[SockID] as NON BLOCKING state_flags = fcntl (listen_socket[SockID], F_GETFL); if (fcntl(listen_socket[SockID], F_SETFL, state_flags | O_NONBLOCK) < 0) printf("\nUnable to put listening Socket in unblocking mode\n"); return (1); }
- La socket de service pour les autres processes.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
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 int Create_ServiceSocket(const char* ipadd, u_short nPort, int SockID) { if (SockID > ClientAllocated-1) { fprintf(stderr, "\nUnable to create client socket! first allocate with Alloc_ListenSocks(int nb);"); return 0; } struct sockaddr_in sin; /* déclaration de la structure sockaddr_in */ int state_flags = 0; /* pour sauvegarder les flags de configuration de cette socket */ memset(&sin, 0x0, sizeof(struct sockaddr_in)); sin.sin_addr.s_addr = inet_addr(ipadd); /* définit l'adresse IP du server */ sin.sin_family = AF_INET; /* famille du socket */ sin.sin_port = htons(nPort); /* port */ service_socket[SockID] = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); /* appel de la fonction socket */ if(service_socket[SockID] != -1) { if (DEBUG_SOCKET_API) fprintf(stdout, "\n[*] Service(client) Socket[%d] successfuly created.\n", SockID); } else { fprintf(stderr, "\nError while creating Service socket[%d], error code: %d\n", SockID, errno); return(0); } if (DEBUG_SOCKET_API) fprintf(stdout, "\nConnection to server\n"); if (!connect(service_socket[SockID], (sockaddr *)&sin, sizeof(struct sockaddr_in)) ) { if (DEBUG_SOCKET_API) fprintf(stdout, " OK!"); } else return(0); // unable to connect to server! // setup service_socket[SockID] as NON BLOCKING state_flags = fcntl (service_socket[SockID], F_GETFL); if (fcntl(service_socket[SockID], F_SETFL, state_flags | O_NONBLOCK) < 0) printf("\nUnable to put 'client' Socket in unblocking mode\n"); return(1); }
J’utilise ce code pour configurer en mode non bloquant (j'avais trouvé la fonction fcntl(...) sous Linux équivalente à FIONBIO(...) je crois sous Win....:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 // setup listen_socket[SockID] as NON BLOCKING state_flags = fcntl (listen_socket[SockID], F_GETFL); if (fcntl(listen_socket[SockID], F_SETFL, state_flags | O_NONBLOCK) < 0) // ajout du flag O_NONBLOCK printf("\nUnable to put listening Socket in unblocking mode\n");
C'est terrible, ça fait un moment que je bloque là dessus, peut-être sauriez vous m'éclairer sur un oubli ou une erreur dans ces fonctions de création et d'initialisation?
Merci par avance
Partager