从零开始写一个简单好用的游戏服务器引擎[2] - 跨平台相关

来源:互联网 发布:java代码实现充值功能 编辑:程序博客网 时间:2024/06/15 10:20

因为项目需要,所以必须做成跨平台的.一方面是历史原因,一方面是有时确实会碰上只有Windows Server或者只有Linux服务器的情况.不过对于服务端来讲,跨平台还是不算太复杂,主要就是以下几个方面:

1.宏定义和类型别名
尽量都向Windows的命名靠拢了.
所以用的时候也以Windows的为标准.

#if defined(_WIN32) || defined(_WIN64)#define LIB_WINDOWS#else#define LIB_LINUX#endif#ifdef LIB_LINUXtypedef unsigned int UINT;typedef unsigned long long ULONGLONG;typedef long long LONGLONG;typedef long long __int64;typedef int BOOL;#define TRUE        1#define FALSE       0typedef int HANDLE;#define INVALID_HANDLE_VALUE ((HANDLE)-1)typedef int INT,*PINT;typedef int SOCKET;typedef unsigned int *PUINT;typedef long LONG_PTR, *PLONG_PTR;typedef int INT_PTR, *PINT_PTR;typedef LONG_PTR SSIZE_T, *PSSIZE_T;typedef unsigned char BYTE;typedef BYTE *LPBYTE;typedef char CHAR;typedef long LONG;typedef wchar_t WCHAR;typedef const char* LPCSTR;typedef char* LPSTR;typedef const wchar_t* LPCWSTR;typedef wchar_t* LPWSTR;typedef unsigned short WORD;typedef unsigned long DWORD;typedef DWORD ULONG;typedef short SHORT;typedef unsigned short USHORT;typedef unsigned long long UINT_PTR, *PUINT_PTR;typedef unsigned long long UINT64;typedef long long INT64;typedef double DOUBLE;typedef void* LPVOID;typedef time_t __time32_t;typedef LONGLONG __time64_t;#ifndef interface#define interface struct#endif

另外就是一些常见的常量宏

#define MAX_PATH 260#define _TRUNCATE ((size_t)-1)#define MAXCHAR         (0x7f)#define MAXSHORT        (0x7fff)#define MAXLONG         (0x7fffffff)#define MAXLONGLONG     (0x7fffffffffffffff)#define MAXINT ((INT)(MAXUINT >> 1))#define MAXUINT ((UINT)~((UINT)0))#define MAXULONG32 ((ULONG32)~((ULONG32)0))#define INFINITE        MAXLONG#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))#define gmtime_s(_tm,_ts)       gmtime_r(_ts,_tm)#define _mktime32       mktime#define ExitProcess     exit#define ZeroMemory(_Dst,_Size) memset((_Dst),0,(_Size))#define GetLastError() errno#define WSAGetLastError() errno#define strcat_s(_Dst,_DstMax,_Src) strncat(_Dst,_Src,_DstMax)#define Sleep(t) usleep((t*1000))#define _ASSERT(_expr) assert(_expr)#define _ASSERTE(_expr) assert(_expr)#define SOCKET_ERROR (-1)#ifndef INVALID_SOCKET#define INVALID_SOCKET -1#define closesocket close

恶心的strcpy&printf大家族

#define strcpy_s        strcpy#define strncpy_s       strncpy#define wcscpy_s        wcscpy#define wcsncpy_s       wcsncpy#define _snprintf_s     snprintf#define sprintf_s       snprintf#define _vsnprintf_s    vsnprintf#define vsnprintf_s     vsnprintf#define vsprintf_s      vsnprintf#define _snwprintf_s    swprintf#define swprintf_s      swprintf#define _vsnwprintf_s   vswprintf#define StrCmpIW        wcscasecmp#define StrCmpIA        strcasecmp#define StrStrIA        strcasestr#define printf_s        printf#endif // LIB_LINUX

基本常用的就这些了.

2.网络库

直接用libevent.本身就跨平台,性能也很好,用起来也很方便.
http://libevent.org/

3.线程&同步锁
线程没什么好说的.

// 线程入口函数#ifdef LIB_WINDOWS    static unsigned WINAPI ThreadProc(LPVOID pParam);#else    static void* ThreadProc(LPVOID pParam);#endif // LIB_WINDOWS
// 线程开启#ifdef LIB_WINDOWS    UINT nThreadID = 0;    HANDLE hThread = (HANDLE)_beginthreadex(NULL,        0,        ThreadProc,        (void*)this,        0,        &nThreadID);    if (hThread == INVALID_HANDLE_VALUE)        return FALSE;#else    UINT nThreadID = 0;    int ret = pthread_create(&nThreadID, NULL, ThreadProc, (void*)this);    if (ret != 0)    {        return FALSE;    }#endif // LIB_WINDOWS

关键是同步锁还是有比较多不同.
直接用宏区分出来封装一下写两份好了.

#ifdef LIB_WINDOWS    class CCriticalSection    {    public:        explicit CCriticalSection(void)        {            InitializeCriticalSectionAndSpinCount(&m_cs, 4000);        }        ~CCriticalSection(void)        {            DeleteCriticalSection(&m_cs);        }        void Lock(void)        {            EnterCriticalSection(&m_cs);        }        void UnLock(void)        {            LeaveCriticalSection(&m_cs);        }    private:        CRITICAL_SECTION m_cs;    };    class CSemaphore    {    public:        CSemaphore(void) :m_hSemaphore(NULL){}        virtual ~CSemaphore(void)        {            if (m_hSemaphore != NULL)            {                CloseHandle(m_hSemaphore);            }        }        BOOL Create(WCHAR *pName, LONG lInitCount, LONG lMaxCount)        {            m_hSemaphore = CreateSemaphore(NULL, lInitCount, lMaxCount, pName);            if (m_hSemaphore == NULL)            {                return FALSE;            }            return  TRUE;        }        BOOL Lock(DWORD  dwTimeOut = INFINITE)        {            DWORD dwReturn = WaitForSingleObject(m_hSemaphore, dwTimeOut);            if (dwReturn == WAIT_OBJECT_0)            {                return TRUE;            }            return  FALSE;        }        BOOL UnLock(LONG lCount)        {            return ReleaseSemaphore(m_hSemaphore, lCount, NULL);        }    private:        HANDLE m_hSemaphore;    };#else    class CCriticalSection    {    public:        explicit CCriticalSection(void)        {            pthread_mutexattr_init(&m_csAttr);            pthread_mutexattr_settype(&m_csAttr, PTHREAD_MUTEX_RECURSIVE_NP);            // 这样创建的原因是因为WindwosCRITICAL_SECTION默认情况下是带有线程递归的.也就是说在同一个线程中允许递归锁.但也要递归解锁到0才能允许其它线程使用.如果不加递归锁属性的话就会在递归加锁时造成死锁!            pthread_mutex_init(&m_cs, &m_csAttr);        }        ~CCriticalSection(void)        {            pthread_mutex_destroy(&m_cs);        }        void Lock(void)        {            pthread_mutex_lock(&m_cs);        }        void UnLock(void)        {            pthread_mutex_unlock(&m_cs);        }    private:        pthread_mutex_t m_cs;        pthread_mutexattr_t m_csAttr;    };    class CSemaphore    {    public:        CSemaphore(void){}        virtual ~CSemaphore(void);        BOOL Lock(DWORD  dwTimeOut = INFINITE)        {// Linux信号量超时锁和非超时锁使用方法有区别            if (dwTimeOut == INFINITE)            {                if (sem_wait(&m_Sem))                {                    return FALSE;                }            }            else            {    #define TIME_USEC   (1000000)                timeval tv;                timespec ts;                gettimeofday(&tv,NULL);                int nSec = (int) (dwTimeOut / 1000);                int nMilSec = dwTimeOut - (nSec * 1000);                tv.tv_sec += nSec;                tv.tv_usec += (nMilSec * 1000);                if (tv.tv_usec > TIME_USEC)                {                    tv.tv_sec += (long)(tv.tv_usec / TIME_USEC);                    tv.tv_usec %= TIME_USEC;                }                ts.tv_sec = tv.tv_sec;                ts.tv_nsec = (tv.tv_usec * 1000);                if (sem_timedwait(&m_Sem, &ts))                {                    return FALSE;                }            }            return TRUE;        }        BOOL UnLock(LONG lCount)        {            if (sem_post(&m_Sem))            {                // Unlock Sem Failed                return FALSE;            }            return TRUE;        }        BOOL Create(WCHAR *pName, LONG lInitCount, LONG lMaxCount)        {            int nRet = sem_init(&m_Sem, 0, 0);            if (nRet)            {                // Create Sem Failed                return FALSE;            }            UnLock(lInitCount);            return TRUE;        }    private:        sem_t m_Sem;    };#endif // LIB_WINDOWS

常用的就这些了.

0 0
原创粉丝点击