Solved

WSAEventSelect returns err WSAENOTSOCK

Posted on 2000-03-22
7
776 Views
Last Modified: 2013-11-20
I have the following code, which basically does: socket();bind();listen();WSAEventSelect();

ALL i want to do is to get events when i recieve TCP message, when client call connect() or when a socket as been closed.

The simple call to WSAEventSelect returns err WSAENOTSOCK.
Why ?

code bellow:
// server.cpp : Defines the entry point for the application.
//

//#include "stdafx.h"
//#include <afxsock.h>

//#include "winsock.h"
#include "winsock2.h"
#include "stdio.h"

enum {
    INIT_FAILED = -1,
    INIT_STRTUP_FAILED = -2,
    ACCEPT_FAILED = -3
};

#define INPUT_BUFFER_SIZE  1000
//TCHAR InputBuffer [INPUT_BUFFER_SIZE];
char InputBuffer [INPUT_BUFFER_SIZE];

#define NUM_OF_SOCKETS  5
SOCKET sock;

SOCKET SockQueue [NUM_OF_SOCKETS];
int SockQueueHead = 0;

void Error (const char *str, ...)
{
    #define BUFF_LEN 255
    char buff [BUFF_LEN];
    va_list arg;

    if (strlen (str) > BUFF_LEN) {
        MessageBox (NULL, "could not allocate buffer for error message", NULL, MB_OK);
        return;
    }

    va_start(arg, str);
    wvsprintf (buff, str, arg);
    va_end(arg);

    MessageBox (NULL, buff, NULL, MB_OK);
}


int Init_WSAStartup(void)
{
    WSADATA wsaData;

    // initiates use of DLL
    if (int i = WSAStartup (MAKEWORD(1,1), &wsaData)) {
        Error ("Socket start-up failed");
        return i;
    }
    if (LOBYTE(wsaData.wVersion) !=1 || HIBYTE(wsaData.wVersion) !=1) {
        Error ("couldn't agree on socket lib version");
        return -1;
    }
    return 0;
}

int Init (void)
{
    if (Init_WSAStartup()) return INIT_STRTUP_FAILED; //do this per process

    return 0;
}

void SocketCleanup (SOCKET s)
{
    int rslt;
    HWND foo = NULL;

    WSAAsyncSelect (s, foo, 1, FD_CLOSE);
    //disable functionality of socket
    shutdown (s, SD_SEND); //SD_SEND declared in winsock2.h as 0x1
    //here i have to insert code to wait for FD_CLOSE
    rslt = recv (s, InputBuffer , sizeof (InputBuffer ), 0);
    while (!((rslt==0) || (rslt==SOCKET_ERROR))) {
        rslt = recv (s, InputBuffer , sizeof (InputBuffer ), 0);
    }
    closesocket (s);

    // remove dll from memory.
    if (WSACleanup () == SOCKET_ERROR) //for each call to WSASrartup, a call to WSACleanup must be issued
        Error ("socket clean-up fail");  
}

void Cleanup (void)
{
    SocketCleanup (sock);
}

int MarkSocketAsBlocking (SOCKET s)
{
    u_long argp = 0L;

    WSAAsyncSelect(s, NULL, 1,0); //disable Async function - last parameter is 0
    //WSAEventSelect(s, NULL, 0);  //disable Event function - last parameter is 0
    //ioctlsocket (s, FIFOBIO, &argp);
    return 0;
}


int MarkSocketAsNonblocking (SOCKET s)
{
    u_long argp = 1L;

    ioctlsocket (s, FIONBIO, &argp); //FIFONBIO defined as 1 in winsock.dll
    return 0;
}


/*int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
*/
int main ()
{
    SOCKADDR_IN local_sin;
    char hostname [100];
    HOSTENT *HostEnt;
      //int  nNumBytes;
    int err;
   
SOCKET NewSock;

    if (Init ()) return INIT_FAILED;
 
    if ((sock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {
        Error ("error %d while openning socket\n", err = WSAGetLastError());
        SocketCleanup (sock);
        return err;
    }


    gethostname(hostname, sizeof (hostname));
    HostEnt = gethostbyname (hostname);
    if (HostEnt == NULL) {
        Error ("error %d from gethostbyname\n", err = WSAGetLastError());
        SocketCleanup (sock);
        return err;
    }

   
    local_sin.sin_family = AF_INET;
    local_sin.sin_port = 10101;
    //local_sin.sin_addr.s_addr = INADDR_ANY;
    memcpy( (LPSTR)&(local_sin.sin_addr), HostEnt->h_addr, HostEnt->h_length);
    if (bind (sock, (const struct sockaddr *) &local_sin, sizeof (local_sin))) {
        Error ("error %d while bind number to socket\n", err = WSAGetLastError());
        SocketCleanup (sock);
        return err;
    }

    if (listen (sock, NUM_OF_SOCKETS)) { // it will be easer to handle just 1 at the first version
        Error ("error %d socket listen\n", err = WSAGetLastError());
        SocketCleanup (sock);
        return err;
    }

    //MarkSocketAsNonblocking (sock);

    WSAEVENT hEvent; //?? init to null ??
    if (WSAEventSelect (sock, hEvent, (long)(FD_READ|FD_WRITE|FD_ACCEPT|FD_CLOSE))) { //FD_CLOSE ?
        Error ("error %d in WSAEventSelect\n", err = WSAGetLastError());
        switch  (err){
        case WSANOTINITIALISED:
            Error ("WSANOTINITIALISED");
            break;
        case WSAENETDOWN:
            Error ("WSAENETDOWN");
            break;
        case WSAEINPROGRESS:
            Error ("WSAEINVAL");
            break;
        case WSAENOTSOCK:
            Error ("WSAENOTSOCK");
            break;
        case WSAEINVAL :
            Error ("WSAEINVAL ");
            break;
        default:
            Error ("default");
        }

  //*/
        // what tod do here ??
        return err;
    }


    WaitForMultipleObjects((DWORD)1, &hEvent, FALSE, INFINITE);
    //struct sockaddr addr;
    //int addrlen;

    //SockQueue[SockQueueHead++] = accept(sock, &addr, &addrlen);
    //if ( SockQueue[SockQueueHead - 1] == SOCKET_ERROR) {      
    NewSock = accept(sock, NULL /*&addr*/, NULL /*&addrlen*/);
    if ( NewSock == SOCKET_ERROR) {      
                  Error ("error %d socket accept\n", err = WSAGetLastError());
                  SocketCleanup (sock);
                  return err;
      }
            
    //Error ("%d %lx %lx", x, &InputBuffer, &InputBuffer[1000]); ??
    recv (NewSock, InputBuffer, sizeof (InputBuffer), 0);
    Error ("%s", InputBuffer);
   
    Cleanup ();
      return 0;
}
0
Comment
Question by:oranm
  • 4
  • 3
7 Comments
 
LVL 3

Accepted Solution

by:
MDarling earned 20 total points
ID: 2645626
Hi,


the answer is simply that you need to create an event to use in the WSAEventSelect call.

instead of

WSAEVENT hEvent;

try

    WSAEVENT hEvent=CreateEvent(0,0,0,0);

and everything should be ok.

regards,
Mike.
0
 

Author Comment

by:oranm
ID: 2645668
Thanks a lot.
It returned no error now.

By the way:
from looking at the code, is it the right way to implement "working in event driven mode" ?

Oran
0
 
LVL 3

Expert Comment

by:MDarling
ID: 2648361
I don't really know what you mean by event driven in this context.

What do you want your program to do?
Is it going to be a single-threaded
or Multi-Thread app?

Will it be used in conjunction in MFC?
If so then Microsofts CAsyncSocket class
would be useful.

I tend to write non gui servers so
mine tend to be multithread apps using
traditional socket callls instead of the
WSAxxx ones.

For example...

socket
bind
listen
accept

with the accept creating a new socket which is passed to a thread which handles the new connection until the connection closes.

MFC also handles this well using the 2
classes CAsyncSocket and CSocket.

regards,
Mike.

0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Author Comment

by:oranm
ID: 2648787
Hi Mike

I have MultiThreaded embedded application.
There is one Thread which is Input side (server), one thread which is the output side (client) and one thread that decide what is the state of the system, based on the input, and send messages to the output.

When I said EventDriven I meant that the input side thread will not run and consume CPU cycles, when no one made connect() or send() to it. Only when there is such event the Input side will "wake up" and deal with it.

I don't know what is MFC and what is the meaning of using it but if it is the correct way to achive what i want, i will do it. (it is the first time i write source under NT OS, so i still don't know a thing with this)

(The application is not a GUI, but use NT so i think calls to GUI calls can be made but they will not appear on a screen)

From your answer i understand that the code i sent you is not the right way to do it(i use WSA..) so I will be happy to know (or even receive code from you ?) what to do.


Thanks

   Oran
0
 
LVL 3

Expert Comment

by:MDarling
ID: 2648843
From your description of your application
there doesnt seem to be anything wrong with the way you are doing it.

It just is different that's all.
I use a traditional method based on Berkely sockets, you are using windows specific stuff, which is fair enough.

Your method will certainly not use excess CPU cycles since it will sleep until an event occurs.

regards,
Mike.
0
 

Author Comment

by:oranm
ID: 2649162
Hi Mike

Thanks again for reassure my fears.
By the way, how can you work with traditional method based on Berkely sockets and be "event driven" for multi threads ? do you must use blocking mode ?

Thanks

   Oran

(oranm at teletron.co.il)
0
 
LVL 3

Expert Comment

by:MDarling
ID: 2649244
spawn a server thread and let it block - it wont take up any cpu time because accept basically does what you're trying to do.

whenever accept is succcessul then go through a loop - create a client thread - give it the new client socket and return to accept again.

if i'm doing a gui app then i use MFC CAsyncSocket - which uses call backs in the windows environment so everything keeps ticking along nicely and you
get notified when you need to do something - like accept a new connection for instance.

regards,
Mike
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
while loop over for loop 7 79
FizzBuzz challenge 9 73
Unix Command -- Challenging  question 7 79
wordmultiple challenge 12 90
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now