| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236 | //// Created by Nathan Touroux on 29/06/2017.//#ifndef NETWORK_NETWORK_H#define NETWORK_NETWORK_H#ifdef WIN32    #include <winsock2.h>    typedef int socklen_t;    #define errno WSAGetLastError()#else    #include <netdb.h>    #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    #define closesocket(s) close (s)    typedef int SOCKET;    typedef struct sockaddr_in SOCKADDR_IN;    typedef struct sockaddr SOCKADDR;#endif // WIN32#include <iostream>#include <vector>#include <unordered_map>#include <thread>#include <atomic>#include <mutex>#include <cstdlib>#include <string.h>#define size_data unsigned longstruct Sock{    SOCKADDR_IN sin;    SOCKET sock = SOCKET_ERROR;    socklen_t recsize = sizeof(sin);    std::string IP = "";    std::string name = "";    int port = 0;};//*********************************************** TCP DATA ***********************************************struct NetPacket{//should be created by NetData, contains length next to the data in "data", "size" is sizeof(size_data)+length of data    void* data;    size_data size;};class NetData{private:    void* data;    size_data size;    void copy(void* data, size_data size);public:    template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type> NetData(T data);    NetData(std::string str);    NetData(const char *str);    NetData(void *data, size_data size, bool copyData = true);    NetData(const NetData ©);    NetData& operator=(const NetData ©);    ~NetData();    bool valid();    template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value>::type> operator T();    operator std::string();    void* getData();    size_data getSize();    NetPacket toPacket();//return a packet (the data inside should be freed)};template<typename T, typename> NetData::NetData(T data): data(nullptr), size(sizeof(T)) {    copy(&data, size);}template<typename T, typename> NetData::operator T() {    if(!valid()) return T();    auto tmp = data;    copy(data, size);    return *static_cast<T*>(tmp);}//*********************************************** TCP CLIENT ***********************************************class TCPServer;class TCPClient{private:    Sock sock;    TCPServer *server;    struct Data{        void* data;        size_data size;        Data* next;    };    Data *first, *last;    int nbData;    std::thread *asyncThread;    std::atomic_bool asynchronous;    std::atomic_bool connected;    std::mutex mutex;    bool invalid();    long unsafeSend(NetData data);    NetData unsafeReceive();    static void asyncReceive(TCPClient *client);    void push(void* data, size_data size);    NetData pop();public:    TCPClient(bool asynchronous = true);    TCPClient(const TCPClient &client);//just copy the asynchronous value    ~TCPClient();    bool accept(TCPServer *server, bool receiveName = false);//if receive name is true, the server must send a string    // (message doesn't import) to confirm that the name is accepted or else disconnect the client    bool connect(std::string IP, int port, std::string name = "");//if a client is already connected with this name the    // connection will fail    void disconnect(bool removeFromServer = true);    bool isConnected();    void enableAsynchronous();    //void disableAsynchronous();    bool asynchronousEnabled();    //WARNING: can't send/receive raw packet when asynchronous    long rawSend(void *data, size_data sizeByte);    long rawReceive(void *data, size_data sizeByte);    long send(NetData data);    NetData receive();//receive a packet with size next to the data so knowing the size isn't important    std::string getIP() const;    std::string getName() const;    int getPort() const;    int getNbData() const;};//*********************************************** TCP SERVEUR ***********************************************class TCPServer{private:#ifdef WIN32    WSADATA m_WSAData;#endif    Sock hsock;    std::vector<TCPClient> clients;    std::unordered_map<std::string, TCPClient*> clientsByIP;    std::unordered_map<std::string, TCPClient*> clientsByName;    std::thread *thread;    int port;    int error;    std::atomic<int> nbConnections;    std::atomic<int> nbConnected;    bool useName;    bool hosting;    bool autoReconnect;    unsigned int maxConnectionTry;    static void waitHost(TCPServer *data);    bool invalid(int client);//return true if there is a problem, false if everything is fine    TCPClient empty;public:    explicit TCPServer(int port, unsigned int nbConnections, bool useName = false, bool asynchronous = true);    ~TCPServer();    bool host(bool waitConnections = false, bool autoReconnect = true, unsigned int maxConnectionTry = -1);    bool acceptHost();//must not be called directly, it is used by host() method    TCPClient& operator[](int index);    TCPClient& operator[](std::string IP);    TCPClient& operator()(std::string name);    TCPClient& unavailable();//use this to compare against a client (ex: server[2] != server.unavailable())    void eraseClient(TCPClient &client);    std::vector<std::string> IPList();    std::vector<std::string> namesList();    Sock getHostSock() const;    int getNbConnected() const;};//*********************************************** UDP ***********************************************class UDP{private:    std::string IP;    int port;    Sock sock;    sockaddr from;    socklen_t fromaddrsize;public:    UDP(std::string IP, int port);// use "" for IP to receive from any IP    ~UDP();    bool init();    long rawSend(void *data, size_data sizeByte);    long rawReceive(void *data, size_data sizeByte);    long send(NetData data);    NetData receive();//receive a packet with size next to the data so knowing the size isn't important    int getPort();    std::string getIP();    //************************************ STATIC ************************************    static long rawSendTo(std::string IP, int port, void *data, size_data sizeByte);    static long sendTo(std::string IP, int port, NetData data);    static long rawReceiveFrom(std::string IP, int port, void *data, size_data sizeByte);    static long rawReceiveFrom(int port, void *data, size_data sizeByte);//TODO add possibility to know from wich ip it comes from    static NetData receiveFrom(std::string IP, int port);    static NetData receiveFrom(int port);};#endif //NETWORK_NETWORK_H
 |