Пример TCP-сервера с использованием модели ввода-вывода WSAE
От: butcher Россия http://bu7cher.blogspot.com
Дата: 04.10.04 09:19
Оценка: 47 (7)
Здравствуйте,
по просьбам трудящихся, subj. Пример простейший, просто, как говорится "для примера" .
Багов не заметил.. Проверял много раз, работает
Выход по Ctrl+C, сервер слушает 5678 порт на всех интерфейсах.
#include    <iostream>
#include    <winsock2.h>
#include    <windows.h>

#pragma        comment (lib, "ws2_32.lib")

const int    SERVER_PORT        =    5678;
const int    BUF_SIZE        =    65535;

BOOL WINAPI    HandlerRoutine(DWORD);

int main (void)
{
    using                std::cout;
    using                std::endl;
    using                std::cerr;

    WSADATA                wd;
    WSAEVENT            hEvents[3];
    SOCKET                sock, lsock, tsock;
    WSANETWORKEVENTS    wsEvents;
    SOCKADDR_IN            saddr;
    DWORD                dwDone = 0, dwCount;
    int                    nRet, nSize;
    char                buf[BUF_SIZE];

    if(nRet = WSAStartup(MAKEWORD(2,0), &wd)){
        cerr << "WSAStartup fail with code " << nRet << endl;
        return -1;
    }
    hEvents[0] = static_cast<WSAEVENT>(CreateEvent(NULL, true, false, "StopProgrammEvent"));
    if(!hEvents[0]){
        cerr << "WSACreateEvent[1] fail with code " << GetLastError () << endl;
        return -2;
    }
    SetConsoleCtrlHandler(HandlerRoutine, true);
    hEvents[1] = WSACreateEvent();
    if (!hEvents[1]){
        cerr << "WSACreateEvent[0] fail with code " << WSAGetLastError() << endl;
        return -3;
    }
    hEvents[2] = WSACreateEvent();
    if(!hEvents[2]){
        cerr << "WSACreateEvent[2] fail with code " << WSAGetLastError() << endl;
        return -4;
    }
    lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if(lsock == INVALID_SOCKET){
        cerr << "socket fail with code " << WSAGetLastError () << endl;
        return -5;
    }
    ZeroMemory(&saddr, sizeof (SOCKADDR_IN));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons (SERVER_PORT);
    saddr.sin_addr.s_addr = INADDR_ANY;
    if(bind(lsock, reinterpret_cast<SOCKADDR*>(&saddr),sizeof(SOCKADDR_IN)))
    {
        cerr << "bind fail with code " << WSAGetLastError () << endl;
        return -6;
    }
    if(listen(lsock, 100)){
        cerr << "listen fail with code " << WSAGetLastError () << endl;
        return -7;
    }
    cout << "Server listen port " << SERVER_PORT << " on " << inet_ntoa (saddr.sin_addr) << endl;
    if(WSAEventSelect(lsock, hEvents[1], FD_ACCEPT)){
        cerr << "WSAEventSelect fail with code " << WSAGetLastError () << endl;
        return -8;
    }
    dwCount = 2;
    while(!dwDone){
        nRet = WSAWaitForMultipleEvents(dwCount, hEvents, false, WSA_INFINITE, false);
        switch (nRet){
            case 0:
                cout << "StopProgrammEvent signaled.. Stopping.." << endl;
                dwDone = 1;
                break;
            case 1:
                if(!WSAEnumNetworkEvents(lsock, hEvents[1], &wsEvents)){
                    if (wsEvents.iErrorCode[FD_ACCEPT_BIT]){
                        cerr << "FD_ACCEPT fail. Stopping.." << endl;
                        dwDone = 1;
                        break;
                    }
                    nSize = sizeof(SOCKADDR_IN);
                    tsock = accept(lsock, reinterpret_cast<SOCKADDR*>(&saddr), &nSize);
                    if(tsock == INVALID_SOCKET){
                        cerr << "accept fail with code " << WSAGetLastError () << endl;
                        break;
                    }
                    cout << "Client connection from: " << inet_ntoa (saddr.sin_addr) << endl;
                    if(dwCount > 2 ){
                        cout << "Connection limit exceeded. Closed." << endl;
                        closesocket (tsock);
                    } else {
                        if (WSAEventSelect(tsock, hEvents[2], FD_READ | FD_CLOSE)){
                            cerr << "WSAEventSelect fail with code " << WSAGetLastError () << endl;
                            cerr << "Stopping.." << endl;
                            dwDone = 1;
                            break;
                        }
                        sock = tsock;
                        dwCount = 3;
                    }
                } else {
                    cerr << "WSAEnumNetworkEvent fail with code " << WSAGetLastError () << endl;
                    ResetEvent (hEvents[1]);
                }
                break;
            case 2:
                if(!WSAEnumNetworkEvents(sock, hEvents[2], &wsEvents)){
                    if(wsEvents.lNetworkEvents & FD_READ){
                        if(wsEvents.iErrorCode[FD_READ_BIT]){
                            cerr << "FD_READ fail. Stopping.." << endl;
                            dwDone = 1;
                            break;
                        } else {
                            nRet = recv(sock, buf, BUF_SIZE, 0);
                            if(nRet > 0) cout << "Received " << nRet << "bytes" << endl;
                        }
                    }
                    if(wsEvents.lNetworkEvents & FD_CLOSE){
                        if(wsEvents.iErrorCode[FD_CLOSE_BIT]){
                            cerr << "FD_CLOSE fail with code " << wsEvents.iErrorCode[FD_CLOSE_BIT] << endl;
                            if(wsEvents.iErrorCode[FD_CLOSE_BIT] == WSAENETDOWN){
                                cerr << "Stopping.." << endl;
                                dwDone = 1;
                                break;
                            }
                        } else {
                            cout << "Client disconnected." << endl;
                            WSAEventSelect(sock, hEvents[2], 0);
                            shutdown(sock, SD_BOTH);
                            closesocket (sock);
                            dwCount = 2;
                        }
                    }
                } else {
                    cerr << "WSAEnumNetworkEvent fail with code " << WSAGetLastError() << endl;
                    WSAResetEvent(hEvents[2]);
                }
                break;
            default:
                cerr << "WSAWaitForMultipleEvents return " << nRet <<" with error code " 
                     << WSAGetLastError() << endl;
        }
    }
    if (dwCount == 3){
        WSAEventSelect(sock, hEvents[2], 0);
        shutdown(sock, SD_BOTH);
        closesocket(sock);
    }
    WSAEventSelect(lsock, hEvents[1], 0);
    for (dwCount = 3; dwCount > 0; dwCount--) 
        WSACloseEvent(hEvents[dwCount-1]);
    closesocket(lsock);
    WSACleanup();
    return 0;
}

BOOL WINAPI    HandlerRoutine(DWORD)
{
    HANDLE    hEvent;
    hEvent = OpenEvent(EVENT_ALL_ACCESS, false, "StopProgrammEvent");
    if(hEvent){
        SetEvent(hEvent);
        CloseHandle(hEvent);
        return true;
    }
    return false;
}

Нет ничего невозможного..
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.