Link to home
Start Free TrialLog in
Avatar of turbot_yu
turbot_yuFlag for Singapore

asked on

Fill the socket address

Hi, May I know how to fill in the IP and port for the socket in the lines below.

Thanks,

Turbot

class CServerSocket  
{
   ....

    SOCKET m_hListeningSocket;
    WSAEVENT m_hAcceptEvent;
    HANDLE m_hListeningThread;
    HANDLE m_hStopListenEvent;
};

void CServerSocket::Initialize(int nPort)
{
    unsigned int dwThreadID;

    // initialize Windows Sockets
    WSADATA wsaData;
    int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    int nError = WSAGetLastError();

    if ( nResult != 0 )     // OK
    {
        PostLogMessage(_T("Winsock initialization failed"));
        PrintErrorDescription(nError);
        return;
    }

    m_bInitialized = TRUE;
    PostLogMessage(_T("Winsock initialization succeeded"));

    // create listening socket
    m_hListeningSocket = WSASocket(
        AF_INET,
        SOCK_STREAM,
        0,
        NULL,
        0,
        WSA_FLAG_OVERLAPPED);         // non-blocking

    nError = WSAGetLastError();

    if ( m_hListeningSocket == INVALID_SOCKET )
    {
        PostLogMessage(_T("Creating of listening socket failed"));
        PrintErrorDescription(nError);
        return;
    }

    // create Accept event
    m_hAcceptEvent = WSACreateEvent();
    nError = WSAGetLastError();

    if ( m_hAcceptEvent == WSA_INVALID_EVENT )
    {
        PostLogMessage(_T("Creating of Accept event failed"));
        PrintErrorDescription(nError);
        return;
    }

    // Associate FD_ACCEPT socket event with m_hAcceptEvent. Now m_hAcceptEvent
    // will be signaled when new client request is received
    // by m_hListeningSocket.
    // m_hAcceptEvent is signaled when accept() may be called whith
    // expectation if immidiate success.
    nResult = WSAEventSelect(m_hListeningSocket,
                             m_hAcceptEvent,
                             FD_ACCEPT);
   
    if ( nResult == SOCKET_ERROR )
    {
        PostLogMessage(_T("WSAEventSelect failed"));
        PrintErrorDescription(nError);
        return;
    }

    // fill SOCKADDR_IN structure
    SOCKADDR_IN     saServer;      

    saServer.sin_port = htons((unsigned short)nPort);
    saServer.sin_family = AF_INET;
    saServer.sin_addr.s_addr = INADDR_ANY;

    // bind SOCKADDR_IN to the listening socket
    nResult = bind(m_hListeningSocket,
                   (LPSOCKADDR)&saServer,
                   sizeof(struct sockaddr));

    if ( nResult == SOCKET_ERROR )
    {
        PostLogMessage(_T("bind function failed"));
        PrintErrorDescription(nError);
        return;
    }

    // Start listening
    nResult = listen(m_hListeningSocket, SOMAXCONN);

    if ( nResult == SOCKET_ERROR )
    {
        PostLogMessage(_T("listen function failed"));
        PrintErrorDescription(nError);
        return;
    }

    // create Stop Listening Thread event
    m_hStopListenEvent = CreateEvent(NULL, TRUE, FALSE, NULL);  // manually reset, initially unsignaled

    if ( ! m_hStopListenEvent )
    {
        PostLogMessage(_T("CreateEvent failed"));
        return;
    }

    // run listening thread

    m_hListeningThread = (HANDLE)_beginthreadex(
        NULL,
        0,
        ListenThreadProc,
        (void*) this,      
        0,
        &dwThreadID);

    if ( m_hListeningThread == NULL )
    {
        PostLogMessage(_T("_beginthreadex for listening threrad failed"));
        return;
    }

    // Show OK message
    PostLogMessage(_T("Server is running"));
}

// this is static function
unsigned CServerSocket::ListenThreadProc(LPVOID lpVoid)
{
    CServerSocket* p  = (CServerSocket*) lpVoid;
    p->ListenThreadFunction();

    return 0;
}

void CServerSocket::ListenThreadFunction()
{
    WSANETWORKEVENTS events;
    DWORD dwResult;
    int nError;
    BOOL bContinue = TRUE;

    HANDLE hEvents[2];
    hEvents[0] = m_hAcceptEvent;
    hEvents[1] = m_hStopListenEvent;

    PostLogMessage(_T("ListenThreadFunction started"));

    while ( bContinue )
    {
        // Wait for asynchronous socket notification (see WSAEventSelect call)
        // and our own stop event

        dwResult = WSAWaitForMultipleEvents(
            2,
            hEvents,
            FALSE,
            INFINITE,
            FALSE);

        nError = WSAGetLastError();
       
        switch ( dwResult )
        {
        case WAIT_OBJECT_0:
            // m_hAcceptEvent event is signaled, new client is connected

            dwResult = WSAEnumNetworkEvents(m_hListeningSocket, m_hAcceptEvent, &events);  // get event type

            nError = WSAGetLastError();

            WSAResetEvent(m_hAcceptEvent);

            if ( dwResult == SOCKET_ERROR )
            {
                PostLogMessage(_T("Error calling WSAEnumNetworkEvents"));
                PrintErrorDescription(nError);
                bContinue = FALSE;
                break;
            }

            // handle signaled network events (we sobscribed to only one - FD_ACCEPT)

            if ( events.lNetworkEvents & FD_ACCEPT )
            {
                // Handle Accept network event. If function returns FALSE (failed), exit
                if ( ! OnAccept(events.iErrorCode[FD_ACCEPT_BIT]) )
                {
                    bContinue = FALSE;
                    break;
                }
            }

            break;

        case WAIT_OBJECT_0 + 1:
            // m_hStopListenEvent is signaled
            bContinue = FALSE;
            break;

        default:
            PostLogMessage(_T("Error calling WSAWaitForMultipleEvents"));
            PrintErrorDescription(nError);
            bContinue = FALSE;
            break;
        }

    }

    PostLogMessage(_T("ListenThreadFunction finished"));
}

void CServerSocket::Cleanup()
{
    int i;
    m_bClosed = TRUE;

    if ( m_hListeningThread )
    {
        // stop listening thread
        SetEvent(m_hStopListenEvent);

        if ( WaitForSingleObject(m_hListeningThread, 3000) != WAIT_OBJECT_0 )
        {
            TerminateThread(m_hListeningThread, 0);
            TRACE(_T("Listening thread is terminated\n"));
        }

        CloseHandle(m_hListeningThread);
    }

    // release events
    if ( m_hStopListenEvent )
    {
        CloseHandle(m_hStopListenEvent);
    }

    if ( m_hAcceptEvent != WSA_INVALID_EVENT )
    {
        WSACloseEvent(m_hAcceptEvent);
    }

    // close listening socket
    if ( m_hListeningSocket != INVALID_SOCKET )
    {
        closesocket(m_hListeningSocket);
    }

    }

    // Close completion port
    if ( m_hCompletionPort )
    {
        CloseHandle(m_hCompletionPort);
    }

    // Sockets cleanup
    if ( m_bInitialized )
        WSACleanup();
}

BOOL CServerSocket::OnAccept(int nErrorCode)
{
    int nResult;
    int nError;

    if ( nErrorCode != 0 )
    {
        PostLogMessage(_T("Accept event error"));
        PrintErrorDescription(nErrorCode);
        return FALSE;
    }

    PostLogMessage(_T("Client connected"));

    // accept new connection
    SOCKADDR_IN SockAddr;           // gets information about client
    SOCKET clientSocket;
    int nAddrLen = sizeof(SOCKADDR_IN);

    clientSocket = accept(m_hListeningSocket,
                          (LPSOCKADDR)&SockAddr,
                          &nAddrLen);

    nError = WSAGetLastError();

    if ( clientSocket == INVALID_SOCKET )
    {
        PostLogMessage(_T("accept function failed"));
        PrintErrorDescription(nError);
        return TRUE;
    }

    // work with clientSocket here, but don't keep caller and return quickly.
    // possibly you need to create thread for client socket and return.
}

ASKER CERTIFIED SOLUTION
Avatar of Craig Wardman
Craig Wardman
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of turbot_yu

ASKER

so it will accept from all the IP, right?
it means it will listen on any IP, it doesnt filter out remote IPs that are connecting..

This is for when a computer has several local IP addresses assigned to it and you might only want to handle a specific IP, but normally you would want to use any, as above..

from MSDN papers:

---
Alternatively, an application may substitute the value INADDR_ANY in place of a valid local IP address, and the system will accept incoming requests on any local interface, and will send requests on the "most appropriate" local interface
---
thanks