Thread: winsock questions

  1. #16
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    i'm using the select() function in my server and it's working good when it's a console, but when i'm trying to use it in window it's a little harder, because since the select() should be in a "while" loop, i don't know where to put it in the code.
    i think i need to use WSAAsyncSelect() but i'm not sure... what u think?

  2. #17
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    If your program creates a window then use WSAAsyncSelect to notify your main window (or any other window) then handle the network events in your window procedure.
    If our program dosen't create any windows then you can either create a message only window for use with WSASyncSelect() or you could still use Select() by putting it in your message loop or putting it in another thread but I would recoment WSASyncSelect().

  3. #18
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    so if i have server which can accept more than one client, i need to use WSAASyncSelect() for each client to get data from it?

  4. #19
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    Quote Originally Posted by hiya
    so if i have server which can accept more than one client, i need to use WSAASyncSelect() for each client to get data from it?
    Thats one way to do it if you decide to use none-blocking sockets. The other way to handle multiple clients is to create a new thread for each client and pass ithe client's socket to the new thread.

  5. #20
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    i don't understand what to do in the second way, can u explain me plz?

  6. #21
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    If you wanted to do it the second way I mentioned then you could create a thread each time you accept a connection.
    Code:
    NewSocket=accept (ListeningSocket, NULL, 0);
    if (NewSocket!=INVALID_SOCKET)
    {
      DWORD ThreadID; 
      HANDLE hThread=CreateThread(NULL, 0, &ServerThread,  NewSocket, 0, &dwThreadID);
       CloseHandle(hThread);
    }
    The function where the new thread begins can accept only one paramater so it can be defined to take the new socket as a paramater.
    Code:
    DWORD ServerThread(SOCKET ClientSocket)
    {
       //...
    }
    Last edited by Quantum1024; 05-08-2005 at 10:38 AM.

  7. #22
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    sorry, i've never used threads..
    after i create a new thread for each client i accept, i pass the socket to a function. what exactly this function should do with it? and how exactly the threads help me? do u know any article about them so i can learn? because i really got no clue on how to use them for my server.

  8. #23
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    your program always starts with a main thread, when you create additional threads they are able to run at the same time as your main thread.
    In the example above CreateThread starts a new thread at the function named ServerThread and passes the socket to that function and then CreateThread returns so that your main thread can keep accepting new connections or doing other things while your new thread is handleing that client. In the new thread you can do all your sending and receiveing to/from the client without affecting your main thread. When you return from the function called by CreateThread that thread exits. Using multie-threading for a server allowys you to handle lots of clients at the same time and keep each client seperate.
    I can't think of any good multie-threading articles, maybe a search of the board would turn up some usefull information.

  9. #24
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    this is my thread function:
    Code:
    DWORD Thread(SOCKET sock)
    {
         //
    }
    and this is how i create a new thread:
    Code:
    DWORD dwThreadID;
    SOCKET sock;
    HANDLE hThread = CreateThread(NULL, 0, Thread, sock, 0, &dwThreadID);
    CloseHandle(hThread);
    but i get an error for the thread creation:
    invalid conversion from `DWORD (*)(SOCKET)' to `DWORD (*)(void*)'

  10. #25
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    solved this problem.
    now, what the thread function should do? run WSAASyncSelect()? or...?

  11. #26
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    That problem is solved by type casting but I guese you allready solved it that way.
    WSAASyncSelect if you want socket events to be reported to a window or select if you just want to check the socket for some event yourself. Since your thread only has one socket to worry about you could just create a loop which receives data, dose something with it then replies with send() if neded. But before calling calling closesocket you should call shutdown on the socket and wait for FD_CLOSE from WSASyncSelect() or check for that event with select() to avoid closeing a socket which still has data pending.

  12. #27
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    i tried something simple:

    accepting the client:
    Code:
    tempSock = accept(listenSock, NULL, 0);
    if(tempSock > 0)
    {
         DWORD dwThreadID;
         HANDLE hThread = CreateThread(NULL, 0, Thread, (LPVOID)tempSock, 0, &dwThreadID);
         CloseHandle(hThread);
    }
    the "Thread()" function:
    Code:
    DWORD WINAPI Thread(LPVOID sock)
    {
         while(true)
         {
              if(recv((SOCKET)sock, NULL, 0, 0) > -1)
                   Msg("recieved data");
         }
    }
    and it should tell me when i get data from the client, but it doesn't give me any message...

  13. #28
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    Code:
    if(recv((SOCKET)sock, NULL, 0, 0) > -1)
    Seams you aren't asking to receive any data.

    Here is a quick working example. It complies in MSVC as a console program but the socket and thread code would work just the same in a WIN32 GUI app.

    Code:
    #include <stdio.h>
    #include <windows.h>
    #include <winsock.h>
    
    DWORD WINAPI Thread(LPVOID);
    
    
    int main()
    {
    	SOCKET listenSock;
    	
    	WSADATA WSAData;
    	if (WSAStartup(MAKEWORD(1,1), &WSAData))
    	{
    		printf("WSAStartup Error %d", WSAGetLastError());
    		return 0;
    	}
    		listenSock=socket(AF_INET, SOCK_STREAM, 0);
    
    	if (listenSock==INVALID_SOCKET)
    	{	printf("Error creating socket\n");
    		return 0;
    	}
    	
    	SOCKADDR_IN LocalAddress;
    	LocalAddress.sin_port=htons(80);
    	LocalAddress.sin_family=AF_INET;
    	LocalAddress.sin_addr.s_addr = INADDR_ANY;
    
    
    	if (bind(listenSock, (SOCKADDR *)&LocalAddress, sizeof(LocalAddress)))
    	{
    		printf("bind() error %d\n", WSAGetLastError());
    		return 0;
    	}
    
    	listen(listenSock, 2);
    	while (TRUE)
    	{
    		SOCKET tempSock = accept(listenSock, NULL, 0);
    
    		if(tempSock!=INVALID_SOCKET)
    		{
    			DWORD dwThreadID;
    			HANDLE hThread = CreateThread(NULL, 0, Thread, (LPVOID)tempSock, 0, &dwThreadID);
    			CloseHandle(hThread);
    		}
    	}
    		return 0;
    }
    
    DWORD WINAPI Thread(LPVOID sock)
    {
        char DataBuffer[1024];
    	
    	while(true)
         {
    		int nRet; 
    		nRet=recv((SOCKET)sock, DataBuffer, 1023, 0);
            if (nRet!=0 && nRet!=SOCKET_ERROR)
    			{	DataBuffer[nRet]=0;//Null terminate
    				printf("Recv->%s\n", DataBuffer);
    			}
    		else
    			{	shutdown((SOCKET)sock, 2);
    				closesocket((SOCKET)sock);
    				return 0;
    			}
    	}
    }
    Remember that recv() dosen't always return the same amount of data as the buffer size so if you know you want a certain amount of data then you need to loop.
    Last edited by Quantum1024; 05-09-2005 at 09:21 AM.

  14. #29
    Registered User
    Join Date
    Apr 2005
    Posts
    98
    if thread is working at the same time WinMain() does, then i can just move my select() function i used in the console to the thread function and i don't need to create threads for each new socket, i just need to add it to the fd_set. am i right?

  15. #30
    Registered User
    Join Date
    Jan 2005
    Posts
    847
    Quote Originally Posted by hiya
    if thread is working at the same time WinMain() does, then i can just move my select() function i used in the console to the thread function and i don't need to create threads for each new socket, i just need to add it to the fd_set. am i right?
    yes you could do that.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Winsock issues
    By tjpanda in forum Windows Programming
    Replies: 3
    Last Post: 12-04-2008, 08:32 AM
  2. 2 questions about winsock 2
    By inhahe in forum Windows Programming
    Replies: 2
    Last Post: 05-13-2008, 11:12 AM
  3. A very long list of questions... maybe to long...
    By Ravens'sWrath in forum C Programming
    Replies: 16
    Last Post: 05-16-2007, 05:36 AM
  4. WinSock questions.
    By p_tyo in forum C++ Programming
    Replies: 2
    Last Post: 01-15-2007, 12:20 AM
  5. Where do I initialize Winsock and catch messages for it?
    By Lithorien in forum Windows Programming
    Replies: 10
    Last Post: 12-30-2004, 12:11 PM