Bonjour,
J'ai une liste de clients qui doivent se connecter sur une liste de serveurs.
J'ai créé 2 exécutables, un pour lancer une multitude de clients dans des threads parallèles, et un pour le serveur. Le code est simplifié, donc c'est normal qu'il manque des contrôles. Voici les codes sources :
Serveur
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
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 #include <stdio.h> #include <winsock2.h> #pragma comment(lib, "Ws2_32.lib") int main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) fprintf(stderr, "La fonction WSAStartup a echoue.\n"); else { SOCKET s_server; s_server = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s_server == INVALID_SOCKET) fprintf(stderr, "La fonction socket a echoue.\n"); else { SOCKADDR_IN server; server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(4999); memset(&server.sin_zero, '\0', sizeof(server.sin_zero)); if (bind(s_server, (SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR) fprintf(stderr, "La fonction bind a echoue.\n"); else { if (listen(s_server, 0) == SOCKET_ERROR) /* listen : commencer l'ecoute */ fprintf(stderr, "La fonction listen a echoue.\n"); else { while (true) { SOCKET s_client; SOCKADDR_IN client; int csize = sizeof(client); s_client = accept(s_server, (SOCKADDR *)&client, &csize); if (s_client == INVALID_SOCKET) fprintf(stderr, "La fonction accept a echoue.\n"); else { char buffer[100]; int n; printf("Le client %s s'est connecte.\n", inet_ntoa(client.sin_addr)); strcpy(buffer, "Bonjour\n"); send(s_client, buffer, (int)strlen(buffer), 0); n = recv(s_client, buffer, sizeof(buffer) - 1, 0); if (n != SOCKET_ERROR) { buffer[n] = '\0'; printf("%s", buffer); } closesocket(s_client); } } } } closesocket(s_server); } WSACleanup(); } return 0; }
Clients
Le client se connecte au serveur via un socket. Je fais un connect de façon asynchrone afin de pour spécifier un timeout de connexion (va select).
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
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162 #include <winsock2.h> #include <stdio.h> #define NB_SOCKS_MAX 10 #pragma comment(lib, "Ws2_32.lib") void WithPool(); void CreatePoolThreads(int iIndexMin, int iIndexMax); int ConnectToServer(char * lpszServer, int iPort); DWORD WINAPI StartThread(LPVOID lpParam); int main() { while (true) { WithPool(); } return EXIT_SUCCESS; } void WithPool() { CreatePoolThreads(115, 130); } void CreatePoolThreads(int iIndexMin, int iIndexMax) { HANDLE achHThread[NB_SOCKS_MAX] = { NULL }; int iIndex = iIndexMin; while (iIndex <= iIndexMax) { int iPoolCount = (iIndex + NB_SOCKS_MAX - 1 <= iIndexMax) ? NB_SOCKS_MAX : iIndexMax - iIndex + 1; int i; for (i = 0; i < iPoolCount; ++i) { achHThread[i] = CreateThread(NULL, 0, static_cast<LPTHREAD_START_ROUTINE>(StartThread), &iIndex, 0, NULL); // Pour laisser le temps au thread de récupérer la valeur de lpParameter Sleep(100); ++iIndex; } WaitForMultipleObjects(iPoolCount, achHThread, TRUE, INFINITE); for (i = 0; i < NB_SOCKS_MAX; ++i) { if (achHThread[i] && (achHThread[i] != INVALID_HANDLE_VALUE)) { CloseHandle(achHThread[i]); achHThread[i] = NULL; } } Sleep(3000); } } int ConnectToServer(char * lpszServer, int iPort) { fprintf(stdout, "Connexion au serveur %s.\n", lpszServer); WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) { fprintf(stderr, "La fonction WSAStartup a echoue.\n"); return -1; } else { SOCKET s; s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == INVALID_SOCKET) { fprintf(stderr, "La fonction socket a echoue (%s).\n", lpszServer); return -1; } else { SOCKADDR_IN server; ULONG fionbio; server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(lpszServer); server.sin_port = htons(iPort); memset(&server.sin_zero, '\0', sizeof(server.sin_zero)); // Mode non-bloquant fionbio = TRUE; ioctlsocket(s, FIONBIO, &fionbio); if ((connect(s, (SOCKADDR *)&server, sizeof(server))) == SOCKET_ERROR) { fd_set writefds; struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO(&writefds); FD_SET(s, &writefds); select(0, NULL, &writefds, NULL, &tv); // Retour au mode bloquant fionbio = FALSE; ioctlsocket(s, FIONBIO, &fionbio); if (FD_ISSET(s, &writefds)) { fprintf(stdout, "%s connecte.\n", lpszServer); char buffer[100]; int n; n = recv(s, buffer, sizeof(buffer) - 1, 0); if (n != SOCKET_ERROR) { buffer[n] = '\0'; printf("%s", buffer); send(s, "Au revoir\n", (int)strlen("Au revoir\n"), 0); } shutdown(s, SD_SEND); } else { fprintf(stdout, "%s non connecte.\n", lpszServer); } } closesocket(s); } WSACleanup(); } return 0; } DWORD WINAPI StartThread(LPVOID lpParam) { char achServer[14]; int iCr; int * lpNum = reinterpret_cast<int *>(lpParam); int i = *lpNum; sprintf(achServer, "%d.0.0.1", i); iCr = ConnectToServer(achServer, 4999); return 0; }
Donc je crée un serveur en localhost, et ensuite je lance 20 clients dans des threads parallèles. J'ai créé des pools de threads car j'ai remarqué qu'on pouvait lancé un nombre limité de sockets simultanées (env 10 lors d'un test mais que je n'arrive plus à reproduire). Les clients vont se connecter à des serveurs différents, dans mon test, j'en ai mis qu'un actif, donc normalement 19 clients n'arriveront pas à joindre leur serveur, et seul un réussira (127.0.0.1).
Toutefois, si j'ai des pools trop grosses de threads (> 6), le client n'arrive pas toujours à se connecter sur le serveur local (paramétrage: NB_SOCKS_MAX => 7, CreatePoolThreads(116, 130)). Et je n'arrive pas à comprendre pourquoi. Est-ce un problème de socket ou autre chose?
Merci d'avance
Partager