Bonjour !
Alors voici la premiere classe qui est partagée:
Voici la deuxieme:
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 #ifndef SELECTOR_H #define SELECTOR_H #if defined __MINGW32__ #include <winsock2.h> #elif defined __GNUC__ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #endif #include <map> #include <vector> #include <iostream> #include "SessionsCollection.h" class ServerSocket; class Selector { public: static const int NO_ACTIVITY = 0; /** Default constructor */ Selector(ServerSocket* ss, SessionsCollection* sc) { server = ss; sessions = sc; online = false; _maxfd = 0; }; /** Default destructor */ ~Selector() {}; int Select() { int r = (online) ? ((_maxfd == 0) ? NO_ACTIVITY : select(_maxfd, &recvfs, NULL, NULL, NULL)) : -1; return r; } bool Ready(int sock) { bool r = (FD_ISSET(sock, &recvfs) == 0) ? false : true; std::cout << "ready? " << sock << ((r) ? "yes":"no")<<std::endl; return r; } void Add(int sock) { FD_SET(sock, &recvfs); _maxfd = sock+1; std::cout << "Added " << sock << " to recvfs"<<std::endl; } void Delete(int sock) { todelete.push_back(sock); } void Mod(int oldsock, int newsock) { FD_CLR(oldsock, &recvfs); _maxfd = 0; FD_SET(newsock, &recvfs); for(auto itr = sessions->AllSessions().begin(); itr != sessions->AllSessions().end(); ++itr) { if(itr->first > _maxfd) { _maxfd = itr->first; } } } void Flush() { int sock; for(auto itr = todelete.begin(); itr != todelete.end(); ++itr) { sock = *itr; FD_CLR(sock, &recvfs); _maxfd = 0; for(auto itr = sessions->AllSessions().begin(); itr != sessions->AllSessions().end(); ++itr) { if(itr->first > _maxfd) { _maxfd = itr->first; } } sessions->DeleteSession(sock); } todelete.clear(); } Session* operator[] (int sock) { return ((sessions->AllSessions().find(sock) != sessions->AllSessions().end()) ? sessions->AllSessions()[sock] : NULL); } inline ServerSocket* Server() { return server; } void PutOnline(bool o) { online = o; } private: ServerSocket* server; SessionsCollection* sessions; std::vector<int> todelete; fd_set recvfs; int _maxfd; bool online; }; #endif // SELECTOR_H
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 #ifndef SESSIONSF_H #define SESSIONSF_H #include <map> #include <iostream> #include "../Tools/Session.h" class Selector; class SessionsCollection { public: /** Default constructor */ SessionsCollection() { }; /** Default destructor */ ~SessionsCollection() {}; void CreateSession(const std::string& ip, const int sock, Selector* slt) { _sessions[sock] = new Session(ip, sock, slt); std::cout << "we have now " << _sessions.size() << " clients"<<std::endl; } void DeleteSession(int sock) { delete _sessions[sock]; _sessions.erase(_sessions.find(sock)); } inline map<int, Session*>& AllSessions() { return _sessions; } inline const int Count() { return _sessions.size(); } void Mod(int oldsock, int newsock) { Session* buf = _sessions[oldsock]; buf->newSock(newsock); _sessions.erase(_sessions.find(oldsock)); _sessions[newsock] = buf; } Session* operator[] (int sock) { return ((_sessions.find(sock) != _sessions.end()) ? _sessions[sock] : NULL); } private: std::map<int, Session*> _sessions; }; #endif // SESSIONS_H
Elles sont donc partagée entre le main(), qui accepte les connexions entrantes, et un thread qui sert exclusivement à la réception des données.
La premiere classe est utilisée pour les macros FD*, ainsi que la fonction select.
La deuxieme est une collections de mes sessions, et permet d'en ajouter/supprimer/modifier.
Ces deux classes sont protegée par un mutex, pour eviter les conflits:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 #ifndef SHARED_H_INCLUDED #define SHARED_H_INCLUDED #include <pthread.h> static pthread_mutex_t SharedMutex = PTHREAD_MUTEX_INITIALIZER; void LockSharedMutex(); void UnlockSharedMutex(); #endif // SHARED_H_INCLUDED
Passons au boucles, voici la boucle dans le main, qui sert à accepter mes connexions:
Ca marche bien, il y a des cout dans CreateSession() & Add(). Aucun probleme.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 while(!shutdown) { Incoming = acceptor->Accept(); if(Incoming.Error == 0) { LockSharedMutex(); sessions->CreateSession(Incoming.IP, Incoming.Socket, selector); selector->Add(Incoming.Socket); UnlockSharedMutex(); } }
Dans le thread, j'ai ceci:
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 while(!shutdown) { LockSharedMutex(); std::cout << "thread: locked mutex" << std::endl; if(Selectr->Select() < 0 || Collection->Count() == 0) { int e = WSAGetLastError(); if (e != 0) { std::cout << "WSA Error: " << e << std::endl; UnlockSharedMutex(); exit(0); } std::cout << "thread: UNLOCKED MUTEX !" << std::endl; UnlockSharedMutex(); continue; } std::cout << "has activicty, loopin on clientz" << std::endl; for(auto itr = Collection->AllSessions().begin(); itr != Collection->AllSessions().end(); ++itr) { Target = itr->second; std::cout << "loop over client (sock=" << itr->first << " /// " << Target->GetSocket() << std::endl; /* code très long :D */ } Selectr->Flush(); UnlockSharedMutex(); std::cout << "thread: UNLOCKED MUTEX !" << std::endl; }
Voici un apercu du probleme :
Le select ne marche donc pas juste apres l'ajout d'un socket dans le descripteur de fichiers.
Une idée ?
merci, nico.
Partager