您的位置:首页 > 其它

跨平台服务开发模板

2013-07-16 11:15 78 查看
  很多时候我们要开发 服务器程序应用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\n",buf);
}

Linux_Win_CloseSocket(socketChild);
Linux_Win_Exit();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: