zoukankan      html  css  js  c++  java
  • 跨平台服务开发模板

      很多时候我们要开发 服务器程序应用linux 和windows平台,很多时候得两套开发代码。我这里选择跨平台开发,已经在windows7 和 ubuntu 12.04 下,经

    过测试,windows 称服务,linux称守护进程, 本质都是一样。

      如果对服务守护进程不是很了解,可以参考【linux c 速学笔记】/【守护进程与socket编程】一章 ttp://www.cnblogs.com/wolfrickwang/p/3192949.html

      关于命名规范问题,由于本程序在windows 平台下面编写,linux 下面测试 所以命名规范偏向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.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 "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
    ",buf);
        }
    
        Linux_Win_CloseSocket(socketChild);
        Linux_Win_Exit();
        return 0;
    }
  • 相关阅读:
    Js $.merge() 函数(合并两个数组内容到第一个数组)
    11.联结表---SQL
    函数作用域
    递归特性
    计算递归函数理解
    递归、问路函数
    全局变量用大写,局部变量用小写
    全局变量与局部变量
    函数形参和实参
    函数和过程
  • 原文地址:https://www.cnblogs.com/wolfrickwang/p/3192941.html
Copyright © 2011-2022 走看看