Bonjour !

Alors voici la premiere classe qui est partagée:
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
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
 
#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:
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();
        }
    }
Ca marche bien, il y a des cout dans CreateSession() & Add(). Aucun probleme.

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.