📄 gsocket.h
字号:
/* Copyright (C) 2006, Mike Gashler This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. see http://www.gnu.org/copyleft/lesser.html*/#ifndef __GSOCKET_H__#define __GSOCKET_H__#include "GMacros.h"#include "GArray.h"#ifdef WIN32#ifndef _MT#error ERROR: _MT not defined. GSocket requires using the multithreaded libraries#define _MT#endif // !_MT#endif // WIN32// Other Includes#ifdef WIN32#ifndef IPPROTO_IP#include <winsock2.h>#endif // IPPROTO_IP#else // WIN32#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#endif // else WIN32#ifndef WIN32typedef struct sockaddr SOCKADDR;typedef struct sockaddr_in SOCKADDR_IN;typedef struct hostent HOSTENT;#endif // WIN32class GPointerQueue;class GSpinLock;class GSocketArray;class GHandleArray;class GKeyPair;class GSecureSocketServer;class GSecureSocketClient;class GPointerArray;class GRand;class GKeyPair;class GIntArray;class GSocketArray : public GDynamicArray{public: GSocketArray(int nGrowBy) : GDynamicArray(sizeof(SOCKET), nGrowBy) { } virtual ~GSocketArray() { } SOCKET GetSocket(int nIndex) { return *(SOCKET*)_GetCellRef(nIndex); } void AddSocket(SOCKET s) { _AddCellByRef(&s); } void SetSocket(int nCell, SOCKET s) { _SetCellByRef(nCell, &s); }};class GSocketClientBase{protected: bool m_bKeepListening; SOCKET m_s; HANDLE m_hListenThread; bool m_bUDP;public: GSocketClientBase(bool bUDP); virtual ~GSocketClientBase(); static bool IsThisAnIPAddress(const char* szHost); // This returns the SOCKET SOCKET GetSocketHandle(); // You should only call Connect for a Client socket bool Connect(const char* szHost, unsigned short nPort); void Disconnect(); bool Send(const unsigned char *pBuf, int nLen); // This method is abstract because you need to implement something here virtual bool Receive(unsigned char *pBuf, int nLen) = 0; // Override me u_short GetMyPort(); struct in_addr GetMyIPAddr(); bool IsConnected(); char* GetMyIPAddr(char* szBuff, int nBuffSize); char* GetMyName(char* szBuff, int nBuffSize); u_short GetTheirPort(); struct in_addr GetTheirIPAddr(); char* GetTheirIPAddr(char* szBuff, int nBuffSize); char* GetTheirName(char* szBuff, int nBuffSize); void Listen(); // Don't call this method directly // This parses a URL into its parts static void ParseURL(const char* szUrl, int* pnHostIndex, int* pnPortIndex, int* pnPathIndex, int* pnParamsIndex); // Parses the parameter portion of a URL static int ParseUrlParams(const char* szParams, int nMaxParams, char** pNames, int* pNameLengths, char** pValues, int* pValueLengths);protected: bool GoIntoHostMode(unsigned short nListenPort, int nMaxConnections); int GetFirstAvailableSocketNumber(); void JoinListenThread(); void JoinListenThread(int nConnectionNumber); // This method is empty. It's just here so you can override it. // This is called when the connection is gracefully closed. (There is no built-in support // for detecting ungraceful disconnects. This is a feature, not a bug, because it makes // it robust to sporadic hardware. I recommend implementing a system where the // server requires the client to send periodic heartbeat packets and you call Disconnect() // if the responses don't come regularly.) virtual void OnCloseConnection();};class GSocketServerBase{protected: SOCKET m_socketConnectionListener; GSocketArray* m_pConnections; GSpinLock* m_pConnectionsLock; fd_set m_socketSet; // structure used by select() HANDLE m_hWorkerThread; bool m_bKeepWorking; SOCKADDR_IN m_sHostAddrIn; bool m_bUDP; int m_nMaxConnections; char* m_szReceiveBuffer;public: GSocketServerBase(bool bUDP, int nPort, int nMaxConnections); virtual ~GSocketServerBase(); // This returns the SOCKET SOCKET GetSocketHandle(int nConnectionNumber); void Disconnect(int nConnectionNumber); bool Send(const unsigned char *pBuf, int nLen, int nConnectionNumber); // This method is abstract because you need to implement something here virtual bool Receive(unsigned char *pBuf, int nLen, int nConnectionNumber) = 0; // Override me // These methods may only work if this is a client socket struct in_addr GetMyIPAddr(); bool IsConnected(int nConnectionNumber); u_short GetTheirPort(int nConnectionNumber); struct in_addr GetTheirIPAddr(int nConnectionNumber); char* GetTheirIPAddr(char* szBuff, int nBuffSize, int nConnectionNumber); char* GetTheirName(char* szBuff, int nBuffSize, int nConnectionNumber); void ServerWorker(); // Don't call this method directlyprotected: void Init(bool bUDP, int nPort, int nMaxConnections); int GetFirstAvailableConnectionNumber(); void JoinWorkerThread(); // This method is empty. It's just here so you can override it. // This is called when the connection is gracefully closed. (There is no built-in support // for detecting ungraceful disconnects. This is a feature, not a bug, because it makes // it robust to sporadic hardware. To detect ungraceful disconnects, I recommend requiring // the client to send periodic heartbeat packets and calling Disconnect() if they stop coming.) virtual void OnCloseConnection(int nConnection); // This method is empty. It's just here so you can override it. // WARNING: the connection isn't fully open at the time this method is called, // so don't send anything back to the client inside this callback virtual void OnAcceptConnection(int nConnection); SOCKET RefreshSocketSet(); void HandleNewConnection(); void ReduceConnectionList();};// --------------------------------------------------------------------------struct GEZSocketPacketHeader{ char tag[4]; int nPayloadSize;};class GSocketMessage{protected: unsigned char* m_pMessage; int m_nMessageSize; int m_nConnection;public: GSocketMessage(unsigned char* pMessage, int nMessageSize, int nConnection) { m_pMessage = new unsigned char[nMessageSize]; GAssert(m_pMessage, "out of memory"); memcpy(m_pMessage, pMessage, nMessageSize); m_nMessageSize = nMessageSize; m_nConnection = nConnection; } virtual ~GSocketMessage() { delete(m_pMessage); } const unsigned char* GetTheMessage() { return m_pMessage; } int GetMessageSize() { return m_nMessageSize; } int GetConnection() { return m_nConnection; } // you must delete the buffer this returns unsigned char* TakeBuffer() { unsigned char* pMessage = m_pMessage; m_pMessage = NULL; return pMessage; }};// --------------------------------------------------------------------------// This class is designed to make network communication easyclass GSocketServer : public GSocketServerBase{protected: GPointerArray* m_pBuffers; int m_nMaxPacketSize; GPointerQueue* m_pMessageQueue; GSpinLock* m_pMessageQueueLock; virtual bool Receive(unsigned char *pBuf, int len, int nConnectionNumber); void QueueMessage(unsigned char* pBuf, int nLen, int nConnectionNumber); GSocketServer(bool bUDP, int nMaxPacketSize, int nPort, int nMaxConnections);public: // Host a TCP socket static GSocketServer* HostTCPSocket(int nPort); // Host a UDP socket static GSocketServer* HostUDPSocket(int nPort); // Host a Gash socket. (Adds a layer on top of TCP to guarantee same-size packet delivery) static GSocketServer* HostGashSocket(int nPort, int nMaxPacketSize); virtual ~GSocketServer(); // Send some data bool Send(const void* pBuf, int nLen, int nConnectionNumber); // Returns the number of messages waiting to be received int GetMessageCount(); // Receive the next message. (You are responsible to delete the buffer this returns) unsigned char* GetNextMessage(int* pnSize, int* pnOutConnectionNumber);};// --------------------------------------------------------------------------// This class is designed to make network communication easyclass GSocketClient : public GSocketClientBase{protected: unsigned char* m_pBuffer; int m_nBufferPos; int m_nMaxPacketSize; GPointerQueue* m_pMessageQueue; GSpinLock* m_pMessageQueueLock; virtual bool Receive(unsigned char *pBuf, int len); void QueueMessage(unsigned char* pBuf, int nLen); GSocketClient(bool bUDP, int nMaxPacketSize);public: // Connect to a TCP socket static GSocketClient* ConnectToTCPSocket(const char* szAddress, int nPort); // Connect to a UDP socket static GSocketClient* ConnectToUDPSocket(const char* szAddress, int nPort); // Connect to a Gash socket. (Adds a layer on top of TCP to guarantee same-size packet delivery) static GSocketClient* ConnectToGashSocket(const char* szAddress, int nPort, int nMaxPacketSize); virtual ~GSocketClient(); // Send some data bool Send(const void* pBuf, int nLen); // Returns the number of messages waiting to be received int GetMessageCount(); // Receive the next message. (You are responsible to delete the buffer this returns) unsigned char* GetNextMessage(int* pnSize);};#endif // __GSOCKET_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -