Windows平台基于多进程的echo服务器简单实现

来源:互联网 发布:批发建筑材料的软件 编辑:程序博客网 时间:2024/06/04 19:46

这里的Echo服务器就是说客户端发什么,服务器端立刻返回什么。一种常见的实现是基于多线程的,在linux上还很容易就用fork实现一个多进程的服务器。

下面演示一下在Windows平台如何用多进程来实现一个echo服务器。


/* *  @file  : TestEchoServerMultiProcess.cpp *  @author: Shilyx *  @date  : 2014-04-23 08:43:27.206 *  @note  : Generated by SlxTemplates, 多进程echo服务器演示 */#include <WinSock2.h>#include <Windows.h>#include <Shlwapi.h>#pragma warning(disable: 4786)#include <iostream>#pragma comment(lib, "Ws2_32.lib")#pragma comment(lib, "Shlwapi.lib")using namespace std;// 初始化WinSock,未检查返回值void InitWinSock(){    WSADATA wd;    WSAStartup(MAKEWORD(2, 2), &wd);}void Serve(USHORT port){    InitWinSock();    SOCKET sock_base = INVALID_SOCKET;    do    {        sock_base = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);        if (sock_base == INVALID_SOCKET)        {            cerr<<"socket error "<<WSAGetLastError()<<endl;            break;        }        sockaddr_in sin;        sin.sin_family = AF_INET;        sin.sin_addr.s_addr = INADDR_ANY;        sin.sin_port = htons(port);        if (SOCKET_ERROR == bind(sock_base, (sockaddr *)&sin, sizeof(sin)))        {            cerr<<"bind error "<<WSAGetLastError()<<endl;            break;        }        if (SOCKET_ERROR == listen(sock_base, 100))        {            cerr<<"listen error "<<WSAGetLastError()<<endl;            break;        }        HANDLE hProcess = NULL;        DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(), GetCurrentProcess(), &hProcess, 0, TRUE, DUPLICATE_SAME_ACCESS);        if (NULL == hProcess)        {            cerr<<"DuplicateHandle error "<<GetLastError()<<endl;            break;        }        TCHAR szSelfPath[MAX_PATH];        GetModuleFileName(GetModuleHandle(NULL), szSelfPath, RTL_NUMBER_OF(szSelfPath));        PathQuoteSpaces(szSelfPath);        while (true)        {            int len = sizeof(sin);            SOCKET sock = accept(sock_base, (sockaddr *)&sin, &len);            if (sock == INVALID_SOCKET)            {                cerr<<"accept error "<<WSAGetLastError()<<endl;                break;            }            else            {                TCHAR szCommand[MAX_PATH * 2];                STARTUPINFO si = {sizeof(si)};                PROCESS_INFORMATION pi;                si.dwFlags = STARTF_USESHOWWINDOW;                si.wShowWindow = SW_SHOW;                wnsprintf(szCommand, RTL_NUMBER_OF(szCommand), TEXT("%s %u %u"), szSelfPath, sock, hProcess);                if (CreateProcess(NULL, szCommand, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))                {                    CloseHandle(pi.hProcess);                    CloseHandle(pi.hThread);                }                else                {                    cerr<<"CreateProcess error "<<GetLastError()<<endl;                }                closesocket(sock);            }        }    } while (false);    if (sock_base != INVALID_SOCKET)    {        closesocket(sock_base);    }}DWORD CALLBACK WorkProc(LPVOID lpParam){    SOCKET sock = (SOCKET)lpParam;    while (TRUE)    {        char szBuffer[4096];        int len = recv(sock, szBuffer, sizeof(szBuffer), 0);        if (len <= 0)        {            break;        }        if (send(sock, szBuffer, len, 0) <= 0)        {            break;        }    }    closesocket(sock);    return 0;}void Work(SOCKET sock, HANDLE hParentProcess){    InitWinSock();    HANDLE hObjects[] = {hParentProcess, CreateThread(NULL, 0, WorkProc, (LPVOID)sock, 0, NULL)};    WaitForMultipleObjects(RTL_NUMBER_OF(hObjects), hObjects, FALSE, INFINITE);    CloseHandle(hObjects[0]);    CloseHandle(hObjects[1]);}int main(int argc, char *argv[]){    // 加端口参数启动为父进程    // 加套接字句柄参数和进程句柄参数为子进程    // 不加参数显示用法    if (argc == 2)    {        int port = StrToIntA(argv[1]);        if (port < 0 || port > 65535)        {            cerr<<"端口错误:"<<port<<endl;            return 0;        }        // 在端口port处启动echo服务器        Serve((USHORT)port);    }    else if (argc == 3)    {        SOCKET sock = StrToIntA(argv[1]);        HANDLE hParentProcess = (HANDLE)StrToIntA(argv[2]);        // 针对具体tcp连接套接字和父进程句柄开始echo工作        Work(sock, hParentProcess);    }    else    {        cout<<"加端口参数启动为父进程"<<endl            <<"加套接字句柄参数和进程句柄参数为子进程"<<endl            <<"不加参数显示用法"<<endl;    }    return 0;}


	
				
		
原创粉丝点击