int HandleNetConn()
{
   int iResult;
   DWORD i;
   DWORD Total;
   ULONG NonBlock;
   DWORD Flags, SendBytes, RecvBytes;
   
	iResult=init_socket();
 
 	if (!iResult)
	{
			// Prepare a socket to listen for connections
		   if (bind(ListenSocket, (PSOCKADDR) &ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR)
			{
			  printf("error in binding the port");
			  closesocket(ListenSocket);
			  WSACleanup();
			  return ERR_SERVER_BIND_FAILED;
		   }

			printf("Bind succeeded");		 

			if (listen(ListenSocket, MAX))
			{
				printf("error in Listening");
				closesocket(ListenSocket);
				WSACleanup();
				return ERR_SERVER_LISTEN_FAILED;
			}	
			
			printf("\n\nServer Listening\n");

		   // Change the socket mode on the listening socket from blocking to

		   // non-block so the application will not block waiting for requests

		   NonBlock = 1;

		   if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
		   {
			  printf("ioctlsocket() failed with error\n");
			  return ERR_IOCTLSOCKET_FAILED;

		   }
	 

		   while(TRUE)
		   {
				// Prepare the Read and Write socket sets for network I/O notification
				FD_ZERO(&ReadSet);
				FD_ZERO(&WriteSet);
				// Always look for connection attempts
				FD_SET(ListenSocket, &ReadSet);

				// Set Read and Write notification for each socket based on the

				// current state the buffer.  If there is data remaining in the

				// buffer then set the Write set otherwise the Read set

				for (i = 0; i < TotalSockets; i++)
				{
						FD_SET(SocketArray[i]->Socket, &ReadSet);
				}

			  if ((Total = select(0, &ReadSet, &WriteSet, NULL, NULL)) == SOCKET_ERROR)
			  {
				 printf("select() returned with error\n");
				 return 1;
			  }
			  else
				printf("select() is OK!\n");

			  // Check for arriving connections on the listening socket.

			  if (FD_ISSET(ListenSocket, &ReadSet))
			  {
				 Total--;
				 if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET)
				 {
					// Set the accepted socket to non-blocking mode so the server will
					// not get caught in a blocked condition on WSASends

					NonBlock = 1;
					if (ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
					{
					   printf("ioctlsocket(FIONBIO) failed with error\n");
					   return 1;
					}
					else
					   printf("ioctlsocket(FIONBIO) is OK!\n");

					if (CreateSocketInformation(AcceptSocket) == FALSE)
					{
						 printf("CreateSocketInformation(AcceptSocket) failed!\n");
						 return 1;
					}
					else
						printf("CreateSocketInformation() is OK!\n");
				 }
				 else
				 {
					if (WSAGetLastError() != WSAEWOULDBLOCK)
					{
					   printf("accept() failed with error\n");
					   return 1;
					}
					else
					   printf("accept() is fine!\n");
				 }
			  }

			  // Check each socket for Read notification until the number
			  // of sockets in Total is satisfied

			  for (i = 0; Total > 0 && i < TotalSockets; i++)
			  {
				 LPSOCKET_INFORMATION SocketInfo = SocketArray[i];

				 // If the ReadSet is marked for this socket then this means data

				 // is available to be read on the socket

				 if (FD_ISSET(SocketInfo->Socket, &ReadSet))

				 {

					Total--;
					SocketInfo->DataBuf.buf = SocketInfo->Buffer;
					SocketInfo->DataBuf.len = DATA_BUFSIZE;
					Flags = 0;

					if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR)
					{
					   if (WSAGetLastError() != WSAEWOULDBLOCK)
					   {
						  printf("WSARecv() failed with error\n");
						  FreeSocketInformation(i);
					   }
					   else
						  printf("WSARecv() is OK!\n");

					   continue;

					}

					else
					{
					   SocketInfo->BytesRECV = RecvBytes;

					   // If zero bytes are received, this indicates the peer closed the connection.

					   if (RecvBytes == 0)
					   {
						  FreeSocketInformation(i);
						  continue;
					   }
					}
				 }
			  }

		   }

		}
		return ERR_SUCCESS;
	}
Пример #2
0
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   SOCKET Accept;
   LPSOCKET_INFORMATION SocketInfo;
   DWORD RecvBytes, SendBytes;
   DWORD Flags;

   if (uMsg == WM_SOCKET)
   {
      if (WSAGETSELECTERROR(lParam))
      {
         printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam));
         FreeSocketInformation(wParam);
      } 
      else
      {
         switch(WSAGETSELECTEVENT(lParam))
         {
            case FD_ACCEPT:

               if ((Accept = accept(wParam, NULL, NULL)) == INVALID_SOCKET)
               {		
                  printf("accept() failed with error %d\n", WSAGetLastError());
                  break;
               }

               // Create a socket information structure to associate with the
               // socket for processing I/O.

               CreateSocketInformation(Accept);

               printf("Socket number %d connected\n", Accept);

               WSAAsyncSelect(Accept, hwnd, WM_SOCKET, FD_READ|FD_WRITE|FD_CLOSE);

               break;

            case FD_READ:

               SocketInfo = GetSocketInformation(wParam);

               // Read data only if the receive buffer is empty.

               if (SocketInfo->BytesRECV != 0)
               {
                  SocketInfo->RecvPosted = TRUE;
                  return 0;
               }
               else
               {
                  SocketInfo->DataBuf.buf = SocketInfo->Buffer;
                  SocketInfo->DataBuf.len = DATA_BUFSIZE;

                  Flags = 0;
                  if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
                     &Flags, NULL, NULL) == SOCKET_ERROR)
                  {
                     if (WSAGetLastError() != WSAEWOULDBLOCK)
                     {
                        printf("WSARecv() failed with error %d\n", WSAGetLastError());
                        FreeSocketInformation(wParam);
                        return 0;
                     }
                  } 
                  else // No error so update the byte count
                  {
                     SocketInfo->BytesRECV = RecvBytes;
                  }
               }

               // DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. Go ahead
               // and begin writing data to the client.

            case FD_WRITE:   			

               SocketInfo = GetSocketInformation(wParam);

               if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
               {
                  SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
                  SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;

                  if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
                     NULL, NULL) == SOCKET_ERROR)
                  {
                     if (WSAGetLastError() != WSAEWOULDBLOCK)
                     {
                        printf("WSASend() failed with error %d\n", WSAGetLastError());
                        FreeSocketInformation(wParam);
                        return 0;
                     }
                  } 
                  else // No error so update the byte count
                  {
                     SocketInfo->BytesSEND += SendBytes;
                  }
               }

               if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
               {
                  SocketInfo->BytesSEND = 0;
                  SocketInfo->BytesRECV = 0;

                  // If a RECV occurred during our SENDs then we need to post an FD_READ
                  // notification on the socket.

                  if (SocketInfo->RecvPosted == TRUE)
                  {
                     SocketInfo->RecvPosted = FALSE;
                     PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
                  }
               }

               break;

            case FD_CLOSE:

               printf("Closing socket %d\n", wParam);
               FreeSocketInformation(wParam);

               break;
         }
      }
      return 0;
   }

   return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Пример #3
0
void *threadIdaServer::Entry()
{

#ifdef _WIN32
	if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
	{
		wxString retString = wxString::Format(wxT("Error creating socket: %d"), WSAGetLastError());
		this->sendDoneEvent(retString, THREAD_IDA_FINISHED_ERROR);

		return NULL;
	}
#endif

	InternetAddr.sin_family = AF_INET;
	InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	InternetAddr.sin_port = htons(port);

	if(bind(ListenSocket, (sockaddr *) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
	{
		wxMutexGuiEnter();
		wxLogDebug(wxT("bind error: %d"), WSAGetLastError());
		wxMutexGuiLeave();

		return NULL;
	}

	if(listen(ListenSocket, MAX_IDA_BACKLOG))
	{
		wxMutexGuiEnter();
		wxLogDebug(wxT("listen error: %d"), WSAGetLastError());
		wxMutexGuiLeave();

		return NULL;
	}

	NonBlock = 1;
	if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
	{
		wxMutexGuiEnter();
		wxLogDebug(wxT("Could not set non-blocking mode: %d"), WSAGetLastError());
		wxMutexGuiLeave();

		return NULL;
	}

	// Set the timeout value
	tv.tv_sec = 1;
	tv.tv_usec = 0;

	wxLogDebug(wxT("IDA Server started"));

	while(1)
	{
		if (this->TestDestroy() == true)
			return NULL;

		FD_ZERO(&ReadSet);
		FD_ZERO(&WriteSet);

		FD_SET(ListenSocket, &ReadSet);

		// Get the items from the list
		m_mutex.Lock();
		DWORD numItems = commandList.size();
		vector<wxString *> commandsToSend;
		for (i = 0 ; i < numItems ; i++)
		{
			commandsToSend.push_back(commandList.back());
			commandList.pop_back();
		}
		m_mutex.Unlock();

		for(i = 0 ; i < TotalSockets ; i++)
		{
			// If we have items to transmit, send them, otherwise check for data to read
			if (commandsToSend.size() > 0)
				FD_SET(SocketArray[i]->Socket, &WriteSet);
			else
				FD_SET(SocketArray[i]->Socket, &ReadSet);
		}

		if ((Total = select(0, &ReadSet, &WriteSet, NULL, &tv)) == SOCKET_ERROR)
		{
			wxMutexGuiEnter();
			wxLogDebug(wxT("Select error: %d"), WSAGetLastError());
			wxMutexGuiLeave();

			return NULL;
		}

		if(FD_ISSET(ListenSocket, &ReadSet))
		{
			Total--;

			if((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET)
			{
				wxMutexGuiEnter();
				wxLogDebug(wxT("Accepted a connection"));
				wxMutexGuiLeave();

				NonBlock = 1;

				if(ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
				{
					wxMutexGuiEnter();
					wxLogDebug(wxT("Error setting socket to non-blocked: %d"), WSAGetLastError());
					wxMutexGuiLeave();

					return NULL;
				}

				if(CreateSocketInformation(AcceptSocket) == FALSE)
				{
					wxMutexGuiEnter();
					wxLogDebug(wxT("CreateSocketInformation error: %d"), WSAGetLastError());
					wxMutexGuiLeave();
				}

				// All is ok if we get here.
			}
			else
			{
				if (WSAGetLastError() != WSAEWOULDBLOCK)
				{
					wxMutexGuiEnter();
					wxLogDebug(wxT("Error with accept: %d"), WSAGetLastError());
					wxMutexGuiLeave();
				}
			}
		}

		// Check the sockets for information
		for (i = 0; Total > 0 && i < TotalSockets;i++)
		{
			LPSOCKET_INFORMATION SocketInfo = SocketArray[i];

			if(FD_ISSET(SocketInfo->Socket, &ReadSet))
			{
				Total--;

				SocketInfo->DataBuf.buf = SocketInfo->Buffer;
				SocketInfo->DataBuf.len = MAX_IDA_SERVER_MSG_SIZE;

				Flags = 0;
				
				// The SocketInfo->DataBuf WSABUF structure should limit the size of received data here
				// according to MSDN http://msdn.microsoft.com/en-us/library/ms741688%28VS.85%29.aspx

#ifdef _WIN32
				if(WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes, &Flags, NULL, NULL) == SOCKET_ERROR)
				{
					if(WSAGetLastError() != WSAEWOULDBLOCK)
					{
						wxMutexGuiEnter();
						wxLogDebug(wxT("Error with recv: %d"), WSAGetLastError());
						wxMutexGuiLeave();

						FreeSocketInformation(i);
						continue;
					}
				}
#else defined _GNUC
				if (false)
				{
					// This is a stub for compilation
				}
#endif
				
				else
				{
					SocketInfo->BytesRECV = RecvBytes;

					// If zero bytes are received this indicates the peer closed the connection.
					if (RecvBytes == 0)
					{
						wxMutexGuiEnter();
						wxLogDebug(wxT("Socket disconnect"));
						wxMutexGuiLeave();

						FreeSocketInformation(i);
						continue;
					}

					size_t len = strlen(SocketInfo->Buffer);
					
					// Trim off the carriage return
					if (len < MAX_IDA_SERVER_MSG_SIZE && len > 0 && SocketInfo->Buffer[len-1] == '\n')
						SocketInfo->Buffer[len-1] = 0;

					// Process the buffer here
					this->sendRecvEvent(new wxString(SocketInfo->Buffer, RecvBytes));

					// Clear the buffer as we're done with it
					memset(SocketInfo->Buffer, 0, sizeof(SocketInfo->Buffer));

				}
			} // End read check

			// If the write set is marked then buffers are ready for more data
			if(FD_ISSET(SocketInfo->Socket, &WriteSet))
			{
				Total--;

				if (commandsToSend.size() > 0)
				{
					wxString *cmd = commandsToSend.back();
					commandsToSend.pop_back();

					// Convert to a C string
					char *cmd_c = (char *) cmd->mb_str(wxConvUTF8);
					size_t len  = strlen(cmd_c);

					// Make sure we only send the proper buffer size
					len = (MAX_IDA_SERVER_MSG_SIZE < len) ? MAX_IDA_SERVER_MSG_SIZE : len;
					
					memcpy(SocketInfo->Buffer, cmd_c, len);

					// We're done with the cmd string now, so free it
					delete cmd;
					cmd = NULL;
					
					SocketInfo->DataBuf.buf = SocketInfo->Buffer;
					SocketInfo->DataBuf.len = len;
				}
				else
				{
					wxMutexGuiEnter();
					wxLogDebug(wxT("Send set with no data available! ERROR"));
					wxMutexGuiLeave();
				}

				if(WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0, NULL, NULL) == SOCKET_ERROR)
				{
					if(WSAGetLastError() != WSAEWOULDBLOCK)
					{
						wxMutexGuiEnter();
						wxLogDebug(wxT("WSA Send error"));
						wxMutexGuiLeave();

						FreeSocketInformation(i);
					}
					else
					{
						wxMutexGuiEnter();
						wxLogDebug(wxT("WSASend() ok"));
						wxMutexGuiLeave();
					}
					
					continue;
				}
				else
				{
					SocketInfo->BytesSEND += SendBytes;

					if(SocketInfo->BytesSEND == SocketInfo->BytesRECV)
					{
						SocketInfo->BytesSEND = 0;
						SocketInfo->BytesRECV = 0;
					}
				} // End Send
			} // End Write check
		} // End socket for loop
	} // End while loop

	return NULL;
}
Пример #4
0
void main(void)
{
	SOCKET Listen;
	SOCKET Accept;
	SOCKADDR_IN InternetAddr;
	DWORD Event;
	WSANETWORKEVENTS NetworkEvents;
	WSADATA wsaData;
	DWORD Ret;
	DWORD Flags;
	DWORD RecvBytes;
	DWORD SendBytes;

	if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
	{
		printf("WSAStartup() failed with error %d\n", Ret);
		return;
	}

	if ((Listen = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
	{
		printf("socket() failed with error %d\n", WSAGetLastError());
		return;
	}

	CreateSocketInformation(Listen);

	if (WSAEventSelect(Listen, EventArray[EventTotal - 1], FD_ACCEPT | FD_CLOSE) == SOCKET_ERROR)
	{
		printf("WSAEventSelect() failed with error %d\n", WSAGetLastError());
		return;
	}

	InternetAddr.sin_family = AF_INET;
	InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	InternetAddr.sin_port = htons(PORT);

	if (bind(Listen, (PSOCKADDR)&InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
	{
		printf("bind() failed with error %d\n", WSAGetLastError());
		return;
	}

	if (listen(Listen, 5))
	{
		printf("listen() failed with error %d\n", WSAGetLastError());
		return;
	}


	while (TRUE)
	{
		// Wait for one of the sockets to receive I/O notification and 
		if ((Event = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE,
			WSA_INFINITE, FALSE)) == WSA_WAIT_FAILED)
		{
			printf("WSAWaitForMultipleEvents failed with error %d\n", WSAGetLastError());
			return;
		}


		if (WSAEnumNetworkEvents(SocketArray[Event - WSA_WAIT_EVENT_0]->Socket, EventArray[Event -
			WSA_WAIT_EVENT_0], &NetworkEvents) == SOCKET_ERROR)
		{
			printf("WSAEnumNetworkEvents failed with error %d\n", WSAGetLastError());
			return;
		}


		if (NetworkEvents.lNetworkEvents & FD_ACCEPT)
		{
			if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)
			{
				printf("FD_ACCEPT failed with error %d\n", NetworkEvents.iErrorCode[FD_ACCEPT_BIT]);
				break;
			}

			if ((Accept = accept(SocketArray[Event - WSA_WAIT_EVENT_0]->Socket, NULL, NULL)) == INVALID_SOCKET)
			{
				printf("accept() failed with error %d\n", WSAGetLastError());
				break;
			}

			if (EventTotal > WSA_MAXIMUM_WAIT_EVENTS)
			{
				printf("Too many connections - closing socket.\n");
				closesocket(Accept);
				break;
			}

			CreateSocketInformation(Accept);

			if (WSAEventSelect(Accept, EventArray[EventTotal - 1], FD_READ | FD_WRITE | FD_CLOSE) == SOCKET_ERROR)
			{
				printf("WSAEventSelect() failed with error %d\n", WSAGetLastError());
				return;
			}

			printf("Socket %d connected\n", Accept);
		}


		// Try to read and write data to and from the data buffer if read and write events occur.

		if (NetworkEvents.lNetworkEvents & FD_READ ||
			NetworkEvents.lNetworkEvents & FD_WRITE)
		{
			if (NetworkEvents.lNetworkEvents & FD_READ &&
				NetworkEvents.iErrorCode[FD_READ_BIT] != 0)
			{
				printf("FD_READ failed with error %d\n", NetworkEvents.iErrorCode[FD_READ_BIT]);
				break;
			}

			if (NetworkEvents.lNetworkEvents & FD_WRITE &&
				NetworkEvents.iErrorCode[FD_WRITE_BIT] != 0)
			{
				printf("FD_WRITE failed with error %d\n", NetworkEvents.iErrorCode[FD_WRITE_BIT]);
				break;
			}

			LPSOCKET_INFORMATION SocketInfo = SocketArray[Event - WSA_WAIT_EVENT_0];

			// Read data only if the receive buffer is empty.

			if (SocketInfo->BytesRECV == 0)
			{
				SocketInfo->DataBuf.buf = SocketInfo->Buffer;
				SocketInfo->DataBuf.len = DATA_BUFSIZE;

				Flags = 0;
				if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
					&Flags, NULL, NULL) == SOCKET_ERROR)
				{
					if (WSAGetLastError() != WSAEWOULDBLOCK)
					{
						printf("WSARecv() failed with error %d\n", WSAGetLastError());
						FreeSocketInformation(Event - WSA_WAIT_EVENT_0);
						return;
					}
				}
				else
				{
					SocketInfo->BytesRECV = RecvBytes;
				}
			}

			// Write buffer data if it is available.

			if (SocketInfo->BytesRECV > SocketInfo->BytesSEND)
			{
				SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
				SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;

				if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
					NULL, NULL) == SOCKET_ERROR)
				{
					if (WSAGetLastError() != WSAEWOULDBLOCK)
					{
						printf("WSASend() failed with error %d\n", WSAGetLastError());
						FreeSocketInformation(Event - WSA_WAIT_EVENT_0);
						return;
					}

					// A WSAEWOULDBLOCK error has occured. An FD_WRITE event will be posted
					// when more buffer space becomes available
				}
				else
				{
					SocketInfo->BytesSEND += SendBytes;

					if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
					{
						SocketInfo->BytesSEND = 0;
						SocketInfo->BytesRECV = 0;
					}
				}
			}
		}

		if (NetworkEvents.lNetworkEvents & FD_CLOSE)
		{
			if (NetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0)
			{
				printf("FD_CLOSE failed with error %d\n", NetworkEvents.iErrorCode[FD_CLOSE_BIT]);
				break;
			}

			printf("Closing socket information %d\n", SocketArray[Event - WSA_WAIT_EVENT_0]->Socket);

			FreeSocketInformation(Event - WSA_WAIT_EVENT_0);
		}
	}
	return;
}
Пример #5
0
void main(void)
{
   SOCKET ListenSocket;
   SOCKET AcceptSocket;
   SOCKADDR_IN InternetAddr;
   WSADATA wsaData;
   INT Ret;
   FD_SET WriteSet;
   FD_SET ReadSet;
   DWORD i;
   DWORD Total;
   ULONG NonBlock;
   DWORD Flags;
   DWORD SendBytes;
   DWORD RecvBytes;


   if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
   {
      printf("WSAStartup() failed with error %d\n", Ret);
      WSACleanup();
      return;
   }

   // Prepare a socket to listen for connections.

   if ((ListenSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
      WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) 
   {
      printf("WSASocket() failed with error %d\n", WSAGetLastError());
      return;
   }

   InternetAddr.sin_family = AF_INET;
   InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
   InternetAddr.sin_port = htons(PORT);

   if (bind(ListenSocket, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr))
      == SOCKET_ERROR)
   {
      printf("bind() failed with error %d\n", WSAGetLastError());
      return;
   }

   if (listen(ListenSocket, 5))
   {
      printf("listen() failed with error %d\n", WSAGetLastError());
      return;
   }

   // Change the socket mode on the listening socket from blocking to
   // non-block so the application will not block waiting for requests.

   NonBlock = 1;
   if (ioctlsocket(ListenSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
   {
      printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
      return;
   }

   while(TRUE)
   {
      // Prepare the Read and Write socket sets for network I/O notification.
      FD_ZERO(&ReadSet);
      FD_ZERO(&WriteSet);

      // Always look for connection attempts.

      FD_SET(ListenSocket, &ReadSet);

      // Set Read and Write notification for each socket based on the
      // current state the buffer.  If there is data remaining in the
      // buffer then set the Write set otherwise the Read set.

      for (i = 0; i < TotalSockets; i++)
         if (SocketArray[i]->BytesRECV > SocketArray[i]->BytesSEND)
            FD_SET(SocketArray[i]->Socket, &WriteSet);
         else
            FD_SET(SocketArray[i]->Socket, &ReadSet);

      if ((Total = select(0, &ReadSet, &WriteSet, NULL, NULL)) == SOCKET_ERROR)
      {
         printf("select() returned with error %d\n", WSAGetLastError());
         return;
      }

      // Check for arriving connections on the listening socket.
      if (FD_ISSET(ListenSocket, &ReadSet))
      {
         Total--;
         if ((AcceptSocket = accept(ListenSocket, NULL, NULL)) != INVALID_SOCKET)
         {

            // Set the accepted socket to non-blocking mode so the server will
            // not get caught in a blocked condition on WSASends

            NonBlock = 1;
            if (ioctlsocket(AcceptSocket, FIONBIO, &NonBlock) == SOCKET_ERROR)
            {
               printf("ioctlsocket() failed with error %d\n", WSAGetLastError());
               return;
            }

            if (CreateSocketInformation(AcceptSocket) == FALSE)
               return;

         }
         else
         {		
            if (WSAGetLastError() != WSAEWOULDBLOCK)
            {
               printf("accept() failed with error %d\n", WSAGetLastError());
               return;
            }
         }
      }

      // Check each socket for Read and Write notification until the number
      // of sockets in Total is satisfied.

      for (i = 0; Total > 0 && i < TotalSockets; i++)
      {
         LPSOCKET_INFORMATION SocketInfo = SocketArray[i];

         // If the ReadSet is marked for this socket then this means data
         // is available to be read on the socket.

         if (FD_ISSET(SocketInfo->Socket, &ReadSet))
         {
            Total--;

            SocketInfo->DataBuf.buf = SocketInfo->Buffer;
            SocketInfo->DataBuf.len = DATA_BUFSIZE;

            Flags = 0;
            if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
               &Flags, NULL, NULL) == SOCKET_ERROR)
            {
               if (WSAGetLastError() != WSAEWOULDBLOCK)
               {
                  printf("WSARecv() failed with error %d\n", WSAGetLastError());

                  FreeSocketInformation(i);
               }

               continue;
            } 
            else
            {
               SocketInfo->BytesRECV = RecvBytes;

               // If zero bytes are received, this indicates the peer closed the
               // connection.
               if (RecvBytes == 0)
               {
                  FreeSocketInformation(i);
                  continue;
               }
            }
         }


         // If the WriteSet is marked on this socket then this means the internal
         // data buffers are available for more data.

         if (FD_ISSET(SocketInfo->Socket, &WriteSet))
         {
            Total--;

            SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
            SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;

            if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
               NULL, NULL) == SOCKET_ERROR)
            {
               if (WSAGetLastError() != WSAEWOULDBLOCK)
               {
                  printf("WSASend() failed with error %d\n", WSAGetLastError());

                  FreeSocketInformation(i);
               }

               continue;
            }
            else
            {
               SocketInfo->BytesSEND += SendBytes;

               if (SocketInfo->BytesSEND == SocketInfo->BytesRECV)
               {
                  SocketInfo->BytesSEND = 0;
                  SocketInfo->BytesRECV = 0;
               }
            }
         }
      }
   }
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
    SOCKET sd;
    LPSOCKET_INFORMATION SocketInfo;
    DWORD RecvBytes, SendBytes;
    DWORD Flags;

    switch (Message) {
    case WM_CREATE:
        createElements(hwnd);
        break;
    case WM_SOCKET:
        if (WSAGETSELECTERROR(lParam)) {
            printf("Socket failed with error %d\n", WSAGETSELECTERROR(lParam));
            FreeSocketInformation(wParam);
        } else {
            switch (WSAGETSELECTEVENT(lParam)) {
            case FD_CONNECT:
                break;
            case FD_ACCEPT:
                if ((sd = accept(wParam, NULL, NULL)) == INVALID_SOCKET) {
                    break;
                }

                CreateSocketInformation(sd);
                
                WSAAsyncSelect(sd, hwnd, WM_SOCKET, FD_READ | FD_CLOSE);
                break;
            case FD_READ:
                SocketInfo = GetSocketInformation(wParam);

                // Read data only if the receive buffer is empty.

                if (SocketInfo->BytesRECV != 0) {
                    SocketInfo->RecvPosted = TRUE;
                    return 0;
                } else {
                    SocketInfo->DataBuf.buf = SocketInfo->Buffer;
                    SocketInfo->DataBuf.len = DATA_BUFSIZE;

                    Flags = 0;
                    if (WSARecv(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &RecvBytes,
                        &Flags, NULL, NULL) == SOCKET_ERROR) {
                        if (WSAGetLastError() != WSAEWOULDBLOCK) {
                            printf("WSARecv() failed with error %d\n", WSAGetLastError());
                            FreeSocketInformation(wParam);
                            return 0;
                        }
                    } else { // No error so update the byte count
                        SocketInfo->BytesRECV = RecvBytes;
                    }
                    break;
                }
                break;
            case FD_WRITE:
                SocketInfo = GetSocketInformation(wParam);

                if (SocketInfo->BytesRECV > SocketInfo->BytesSEND) {
                    SocketInfo->DataBuf.buf = SocketInfo->Buffer + SocketInfo->BytesSEND;
                    SocketInfo->DataBuf.len = SocketInfo->BytesRECV - SocketInfo->BytesSEND;

                    if (WSASend(SocketInfo->Socket, &(SocketInfo->DataBuf), 1, &SendBytes, 0,
                        NULL, NULL) == SOCKET_ERROR) {
                        if (WSAGetLastError() != WSAEWOULDBLOCK) {
                            printf("WSASend() failed with error %d\n", WSAGetLastError());
                            FreeSocketInformation(wParam);
                            return 0;
                        }
                    }
                    else { // No error so update the byte count
                        SocketInfo->BytesSEND += SendBytes;
                    }
                }

                if (SocketInfo->BytesSEND == SocketInfo->BytesRECV) {
                    SocketInfo->BytesSEND = 0;
                    SocketInfo->BytesRECV = 0;

                    // If a RECV occurred during our SENDs then we need to post an FD_READ
                    // notification on the socket.

                    if (SocketInfo->RecvPosted == TRUE) {
                        SocketInfo->RecvPosted = FALSE;
                        PostMessage(hwnd, WM_SOCKET, wParam, FD_READ);
                    }
                }
                break;
            case FD_CLOSE:
                printf("Closing socket %d\n", wParam);
                FreeSocketInformation(wParam);
                break;
            }
        }
        break;
    case WM_DESTROY:	// Terminate program
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    return 0;
}