跨平臺服務開發模板

  不少時候咱們要開發 服務器程序應用linux 和windows平臺,不少時候得兩套開發代碼。我這裏選擇跨平臺開發,已經在windows7 和 ubuntu 12.04 下,經html

過測試,windows 稱服務,linux稱守護進程, 本質都是同樣。linux

  若是對服務守護進程不是很瞭解,能夠參考【linux c 速學筆記】/【守護進程與socket編程】一章 ttp://www.cnblogs.com/wolfrickwang/p/3192949.html編程

  關於命名規範問題,因爲本程序在windows 平臺下面編寫,linux 下面測試 因此命名規範偏向windows 平臺開發慣用命名規範。ubuntu

   現將代碼張貼以下:windows

 

(1)公共頭文件源碼  server.h服務器

#ifndef    _SERVER_H_
#define _SERVER_H_

#ifdef WIN32 //Windows下定義
    #include <winsock.h>

    #define Linux_Win_SOCKET    SOCKET                         //定義Socket套接字變量類型
    #define Linux_Win_CloseSocket closesocket
    #define Linux_Win_F_INET    AF_INET                        //協議族命名約定
    #define Linux_Win_InvalidSocket INVALID_SOCKET            //非法的socket表示值定義
    #define Linux_Win_SocketError   SOCKET_ERROR            //標準socket錯誤返回碼
    #define Linux_Win_SetSockOptArg4UseType const char        //setsockopt第4個變量類型定義
    #define Linux_Win_GetSockOptArg4UseType char            //getsockopt第4個變量類型定義
    #define Linux_Win_SendRecvLastArg 0                        //send recv函數的最後一個參數類型



   
    //注意此處,全部的錯誤返回碼定名,Windows平臺向向標準的伯克利socket規範靠攏。
    #define EWOULDBLOCK        WSAEWOULDBLOCK //10035
    #define EINPROGRESS        WSAEINPROGRESS
    #define EALREADY        WSAEALREADY
    #define ENOTSOCK        WSAENOTSOCK
    #define EDESTADDRREQ    WSAEDESTADDRREQ
    #define EMSGSIZE        WSAEMSGSIZE
    #define EPROTOTYPE        WSAEPROTOTYPE
    #define ENOPROTOOPT        WSAENOPROTOOPT
    #define EPROTONOSUPPORT    WSAEPROTONOSUPPORT
    #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
    #define EOPNOTSUPP        WSAEOPNOTSUPP
    #define EPFNOSUPPORT    WSAEPFNOSUPPORT
    #define EAFNOSUPPORT    WSAEAFNOSUPPORT
    #define EADDRINUSE        WSAEADDRINUSE
    #define EADDRNOTAVAIL    WSAEADDRNOTAVAIL
    #define ENETDOWN        WSAENETDOWN
    #define ENETUNREACH        WSAENETUNREACH
    #define ENETRESET        WSAENETRESET
    #define ECONNABORTED    WSAECONNABORTED//10053
    #define ECONNRESET        WSAECONNRESET //10054
    #define ENOBUFS            WSAENOBUFS
    #define EISCONN            WSAEISCONN
    #define ENOTCONN        WSAENOTCONN
    #define ESHUTDOWN        WSAESHUTDOWN
    #define ETOOMANYREFS    WSAETOOMANYREFS
    #define ETIMEDOUT        WSAETIMEDOUT
    #define ECONNREFUSED    WSAECONNREFUSED
    #define ELOOP            WSAELOOP
    #define EHOSTDOWN        WSAEHOSTDOWN
    #define EHOSTUNREACH    WSAEHOSTUNREACH
    #define EPROCLIM        WSAEPROCLIM
    #define EUSERS            WSAEUSERS
    #define EDQUOT            WSAEDQUOT
    #define ESTALE            WSAESTALE
    #define EREMOTE            WSAEREMOTE
    
#else //Linux下定義

    #define Linux_Win_SOCKET int    //定義Socket套接字變量類型
    #define Linux_Win_CloseSocket close
    #define Linux_Win_F_INET AF_INET    //協議族命名約定
    #define Linux_Win_InvalidSocket -1  //非法的socket表示值定義    
    #define Linux_Win_SocketError -1    //標準socket錯誤返回碼    
    #define Linux_Win_SetSockOptArg4UseType void    //setsockopt第4個變量類型定義    
    #define Linux_Win_GetSockOptArg4UseType void     //getsockopt第4個變量類型定義      
    #define Linux_Win_SendRecvLastArg MSG_NOSIGNAL  //send recv函數的最後一個參數類型

        
    #define Sleep(ms) usleep(ms*1000)
    
#endif


#endif

 

 

(二) 服務器端代碼 server.csocket

/********************************

    @跨平臺開發服務測試

********************************/
#ifdef WIN32
    #include <windows.h>
    #include <winioctl.h>
    #include <tchar.h>

    #define UPDATE_TIME 1000*3
    static LPWSTR serviceName = _T("SERVER");
    static SERVICE_STATUS hServStatus;
    static SERVICE_STATUS_HANDLE hSStat; 

#else
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <signal.h>
    #include <sys/param.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
#endif

#include "server.h"


static int g_ServeExit = 0;
//entry
int    ServerEntry(void);



#ifdef WIN32
void UpServiceStatus (int NewStatus, int Check)
{
    if (Check < 0 ) 
    {
        hServStatus.dwCheckPoint++;
    }
    else            
    {
        hServStatus.dwCheckPoint = Check;
    }

    if (NewStatus >= 0) 
    {
        hServStatus.dwCurrentState = NewStatus;
    }
    if (!SetServiceStatus (hSStat, &hServStatus)) 
    {
        hServStatus.dwCurrentState = SERVICE_STOPPED;
        hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
        hServStatus.dwServiceSpecificExitCode = 2;
        UpServiceStatus (SERVICE_STOPPED, -1);
        return;
    } 
 
}

void WINAPI ServerCtrlHandler(DWORD dwControl)
{
    switch (dwControl) 
    {
    case SERVICE_CONTROL_SHUTDOWN:
    case SERVICE_CONTROL_STOP:
        g_ServeExit = 1;
        UpServiceStatus (SERVICE_STOP_PENDING, -1);
        break;
//    case SERVICE_CONTROL_PAUSE:
//        break;
//    case SERVICE_CONTROL_CONTINUE:
//        break;
//    case SERVICE_CONTROL_INTERROGATE:
//        break;
    default:
        break;
    }
    UpServiceStatus(-1, -1);
    return;
    }


void WINAPI ServiceMain (DWORD argc, LPWSTR  *lpServiceArgVectors )    // char *argv[])
{
    hServStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    hServStatus.dwCurrentState = SERVICE_START_PENDING;
    hServStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |     SERVICE_ACCEPT_SHUTDOWN;
    hServStatus.dwWin32ExitCode = NO_ERROR;
    hServStatus.dwServiceSpecificExitCode = 0;
    hServStatus.dwCheckPoint = 0;
    hServStatus.dwWaitHint = 2 * UPDATE_TIME;
    hSStat = RegisterServiceCtrlHandler( serviceName, ServerCtrlHandler);
    if (hSStat == 0) 
    {
            hServStatus.dwCurrentState = SERVICE_STOPPED;
            hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
            hServStatus.dwServiceSpecificExitCode = 1;
            UpServiceStatus (SERVICE_STOPPED, -1);
            return;
    }
    SetServiceStatus (hSStat, &hServStatus);

    //Entry server
    if (ServerEntry ()!= 0) 
    {
        hServStatus.dwCurrentState = SERVICE_STOPPED;
        hServStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
        hServStatus.dwServiceSpecificExitCode = 1;  /* Server initilization failed */
        SetServiceStatus (hSStat, &hServStatus);
        return;
    }
    UpServiceStatus(SERVICE_STOPPED, 0);
    return ;
}

#else

void InitDaemon(void)
{
    int pid;
    int i;
    if(pid=fork())
        exit(0);        //是父進程,結束父進程
    else if(pid< 0)
        exit(1);        //fork失敗,退出
    //是第一子進程,後臺繼續執行
    setsid();           //第一子進程成爲新的會話組長和進程組長
    //並與控制終端分離
    if(pid=fork())
        exit(0);        //是第一子進程,結束第一子進程
    else if(pid< 0)
        exit(1);        //fork失敗,退出
    //是第二子進程,繼續
    //第二子進程再也不是會話組長
    for(i=0;i< NOFILE;++i)  //關閉打開的文件描述符
        close(i);

    chdir("/tmp");      //改變工做目錄到/tmp
    umask(0);           //重設文件建立掩模
    return;
}


LinuxCreateServer()
{
    InitDaemon();
    ServerEntry();    
}

#endif



//the main
int main(int argc, char* argv[])
{

#ifdef WIN32
    SERVICE_TABLE_ENTRY ServiceTable[]=
    {
        {serviceName,ServiceMain},
        {NULL,NULL}
    };
#endif

    if (argc == 1 ) //server entry has no param
    {
#ifdef WIN32
        StartServiceCtrlDispatcher(ServiceTable); 
#else
        LinuxCreateServer();
#endif
    }
    else        //no server  for Debug mode
    {
        ServerEntry();
    }
    return 0;
}

/*************************************************************
@
@
@
*************************************************************/
#ifdef WIN32        //win32
    #pragma comment(lib,"wsock32")    //dll庫調用準備

#endif

void Linux_Win_Init()                //win 32 socket初始化代碼
{
#ifdef WIN32
    WORD wVersionRequested;
    WSADATA wsaData;        
    wVersionRequested = MAKEWORD(2, 2 );
    WSAStartup( wVersionRequested, &wsaData );
#endif
}

void Linux_Win_Exit() //win32 socket結束代碼
{
#ifdef WIN32
        WSACleanup( );
#endif
}

#define     MAX_CLIENT        30        
#define  SERVER_PORT    8111
#define  SOSKET_BUFSIZE 1024

//entry the server
int    ServerEntry(void)
{
    Linux_Win_SOCKET socketServer;
    Linux_Win_SOCKET socketChild;
    struct sockaddr_in serveDdr;
    struct sockaddr_in clildDdr;

    int    socketAddLen;
    char buf[SOSKET_BUFSIZE] = {"YOUR    SOCKET  LINKED"};

    Linux_Win_Init();

    socketServer = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serveDdr,0,sizeof(serveDdr));
    serveDdr.sin_family = AF_INET;
    serveDdr.sin_addr.s_addr = htonl(INADDR_ANY);
    serveDdr.sin_port = htons(SERVER_PORT);

    bind(socketServer, (struct sockaddr *)&serveDdr, sizeof(serveDdr));
    listen(socketServer, MAX_CLIENT);

    while (!g_ServeExit) 
    {
        socketAddLen = sizeof(clildDdr);
        socketChild = accept(socketServer,(struct sockaddr *)&clildDdr,  &socketAddLen);
        send(socketChild, buf, SOSKET_BUFSIZE,Linux_Win_SendRecvLastArg);

        Sleep(1);
        Linux_Win_CloseSocket(socketChild);
    }

    Linux_Win_Exit();
    return 1;
}

(3) 客戶端代碼 client.c函數

#ifdef WIN32
#include <windows.h>
#include <winioctl.h>
#include <tchar.h>

#define UPDATE_TIME 1000*3
static LPWSTR serviceName = _T("SERVER");
static SERVICE_STATUS hServStatus;
static SERVICE_STATUS_HANDLE hSStat; 

#else
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#endif

#include <stdio.h>
#include "server.h"


#ifdef WIN32        //win32
#pragma comment(lib,"wsock32")    //dll庫調用準備

#endif

void Linux_Win_Init()                //win 32 socket初始化代碼
{
#ifdef WIN32
    WORD wVersionRequested;
    WSADATA wsaData;        
    wVersionRequested = MAKEWORD(2, 2 );
    WSAStartup( wVersionRequested, &wsaData );
#endif
}

void Linux_Win_Exit() //win32 socket結束代碼
{
#ifdef WIN32
    WSACleanup( );
#endif
}

#define  SERVER_PORT    8111
#define  SOSKET_BUFSIZE 1024
#define     SERVER_IP    "192.168.3.36"    

int main()
{
    Linux_Win_SOCKET socketChild;
    struct sockaddr_in serveDdr;

    char buf[SOSKET_BUFSIZE] = {0};

    Linux_Win_Init();

    socketChild = socket(AF_INET, SOCK_STREAM, 0);

    memset(&serveDdr,0,sizeof(serveDdr));
    
    serveDdr.sin_family = AF_INET;

    serveDdr.sin_addr.s_addr = inet_addr(SERVER_IP);    

//    inet_pton(AF_INET, SERVER_IP, &serveDdr.sin_addr);

    serveDdr.sin_port = htons(SERVER_PORT);

    if(Linux_Win_SocketError != connect(socketChild, (struct sockaddr *)&serveDdr, sizeof(serveDdr)) )
    {
        recv(socketChild,buf,SOSKET_BUFSIZE,Linux_Win_SendRecvLastArg);
        printf("receive string: %s\n",buf);
    }

    Linux_Win_CloseSocket(socketChild);
    Linux_Win_Exit();
    return 0;
}
相關文章
相關標籤/搜索