Home
  Home
Home
Search
Articles
Page Tag-Cloud
  Software
Software Tag-Cloud
Submit Patch
Building from Source
Open Source Definition
  Popular Tags
C++
Source Code
Class
Legacy
Cryptography
  Members
Login
Web-Email
Notable Members
  Official
Our Company
Copyright Information
Software EULA
GPL EULA
LGPL Eula
Pre-Release EULA
Privacy Policy
  Support
Make Contact
 
 
Sockets in Win32

The foundation of a computer's social life.

From experience, sockets in C/C++ can be very off-putting. This is "not so" in the case of (near post-) modern languages with a greater level of abstraction (Python, C#, VB.NET, ect, ect) but for good ol' Win32 – you've got your work cut out for you.
 
All this work is not without its rewards! You can create blocking mode clients, asynchronous load-balanced services, super-high throughput applications and seriously reliable programs using only a few simple functions in WinSock.
 
As a side note, it should be known that "WinSock" should seriously be called BSDSock as it was an outright copy from BSD – the windows source code even bears the BSD copyright notices (though I've heard through the grape-vine that Microsoft has rewritten the IP-Stack while in the process of building up support for IPv6 – but that is only speculation on my end).
 
I've highly commented and trimmed down this not-so-fully featured web server for your enjoyment!

(double-click to select in copy/paste friendly fashion)
#include "windows.h"
#include "winsock.h"
#include "stdio.h"
 
//be sure to include the linker library: wsock32.lib
 
#define MAX_CONNECTIONS 25
#define MAX_RECV_SIZE 8120
 
int main(int argc, char *argv[])
{
 SOCKET listenSocket = NULL; //The socket that will listen for new connections.
 SOCKET peerSockets[MAX_CONNECTIONS];
 SOCKET peerBytesSent[MAX_CONNECTIONS];
 
 struct timeval tTimeOut; // The TimeOut structure.
 tTimeOut.tv_sec = 1;
 tTimeOut.tv_usec = 0;
 
 //These are used to identify if a socket is ready
 // for reading, writing or is experiencing an exception.
 fd_set fdRead;
 fd_set fdWrite;
 fd_set fdExcept;
 
 WORD WSARequiredVersion = 0x0101; // Version 1.1
 WSADATA WSAData;
 WSADATA *WSAPointerData = &WSAData;
 if(WSAStartup(WSARequiredVersion, WSAPointerData) != 0)
 {
  printf("Failed to initialize WinSock: %d\n", WSAGetLastError());
  return 1;
 }
 
 // Fill In The Address Structure For Local Server
 SOCKADDR_IN localSockAddress; // Socket address of local server
 localSockAddress.sin_family      = AF_INET;    // Address Family.
 localSockAddress.sin_addr.s_addr = INADDR_ANY; // Library assigned address.
 localSockAddress.sin_port   = htons(80);  // Port Number.
 
 // Create A TCP/IP Stream Socket To "Listen" with.
 if((listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
 {
  printf("Failed to create socket: %d\n", WSAGetLastError());
  WSACleanup();
  return 1;
 }
 
 // Bind The Name To The Socket.
 if(bind(listenSocket, (SOCKADDR*)&localSockAddress, sizeof(struct sockaddr)) == SOCKET_ERROR)
 {
  printf("Bind failed: %d\n", WSAGetLastError());
  closesocket(listenSocket);
  WSACleanup();
  return 1;
 }
 
 // Set The Socket To Listen.
 if(listen(listenSocket, MAX_CONNECTIONS) == SOCKET_ERROR)
 {
  printf("Listen failed: %d\n", WSAGetLastError());
  closesocket(listenSocket);
  WSACleanup();
  return 1;
 }
 
 memset(&peerSockets, 0, sizeof(SOCKET) * MAX_CONNECTIONS);
 memset(&peerBytesSent, 0, sizeof(int) * MAX_CONNECTIONS);
 
 //---------------------------------------------------------
 
 while(true)
 {
  // Zero the Read, Write and Except descriptors.
  FD_ZERO(&fdRead);
  FD_ZERO(&fdWrite);
  FD_ZERO(&fdExcept);
 
  //Add the listen socket to the descriptor array.
  FD_SET(listenSocket, &fdRead);
  FD_SET(listenSocket, &fdExcept);
 
  //Add all connected sockets to the descriptor array.
  for(int i = 0; i < MAX_CONNECTIONS; i++)
  {
   if(peerSockets[i])
   {
    FD_SET(peerSockets[i], &fdRead);
    FD_SET(peerSockets[i], &fdWrite);
    FD_SET(peerSockets[i], &fdExcept);
   }
  }
 
  //Socket Select. This will figure out the disposition
  // of all the sockets in the descriptor array.
  if(select(-1, &fdRead, &fdWrite, &fdExcept, &tTimeOut) == SOCKET_ERROR)
  {
   printf("Select failed: %d\n", WSAGetLastError());
   closesocket(listenSocket);
   break;
  }
 
  //Are there any waiting connections?
  if(FD_ISSET(listenSocket, &fdRead))
  {
   int iLength = 0;
   SOCKET peerSocket = 0;
 
   SOCKADDR_IN remoteSockAddr;
   int iAddressLength = sizeof(SOCKADDR);
 
   //Accept the connection.
   peerSocket = accept(listenSocket, (SOCKADDR*)&remoteSockAddr, &iAddressLength);
 
   if(peerSocket == SOCKET_ERROR)
   {
    printf("Accept failed: %d\n", WSAGetLastError());
    closesocket(listenSocket);
    break;
   }
   else if(peerSocket == 0)
   {
    printf("Accept failed (gracefully): %d\n", WSAGetLastError());
    closesocket(listenSocket);
    break;
   }
 
   bool bFoundFreeSocket = false;
 
   //Find a free socket in the socket array.
   for(int i = 0; i < MAX_CONNECTIONS; i++)
   {
    if(peerSockets[i] == NULL)
    {
     peerSockets[i] = peerSocket;
     bFoundFreeSocket = true;
     break;
    }
   }
 
   if(!bFoundFreeSocket)
   {
    printf("No free sockets\n");
    closesocket(listenSocket);
   }
  } //if(FD_ISSET(listenSocket, &fdRead))
   
  //Check the disposition of each connected socket.
  for(int i = 0; i < MAX_CONNECTIONS; i++)
  {
   if(peerSockets[i])
   {
    //Is data waiting to be received?
    if(FD_ISSET(peerSockets[i], &fdRead))
    {
     char recvBuffer[MAX_RECV_SIZE];
     int recvLength = recv(peerSockets[i],
      recvBuffer, sizeof(recvBuffer), 0);
 
     if(recvLength == SOCKET_ERROR)
     {
      //Disconnect the socket.
      closesocket(peerSockets[i]);
      peerSockets[i] = NULL;
      peerBytesSent[i] = 0;
     }
     else if(recvLength == 0) // Gracefull disconnect.
     {
      //Disconnect the socket.
      closesocket(peerSockets[i]);
      peerSockets[i] = NULL;
      peerBytesSent[i] = 0;
     }
     else{
      recvBuffer[recvLength] = '\0';
      printf("Received %d bytes: \"%s\"\n", recvLength, recvBuffer);
     }
    }
 
    //Is the socket ready to accept data?
    if(FD_ISSET(peerSockets[i], &fdWrite))
    {
     //Send some data back to the connected peer.
 
     char *sendBuffer = "Hello World";
 
     int bytesSent = send(peerSockets[i], sendBuffer, strlen(sendBuffer), 0);
     if(bytesSent == SOCKET_ERROR)
     {
      int iLastError = WSAGetLastError();
      if(iLastError == WSAEWOULDBLOCK || iLastError == WSAEINPROGRESS)
      {
       //Do nothing, try to send again on the the next go-round.
      }
      else{
       //Disconnect the socket.
       closesocket(peerSockets[i]);
       peerSockets[i] = NULL;
       peerBytesSent[i] = 0;
      }
     }
     else if(bytesSent == 0)
     {
      //Disconnect the socket.
      closesocket(peerSockets[i]);
      peerSockets[i] = NULL;
      peerBytesSent[i] = 0;
     }
     else {
      //Data was sent successfully!
 
      //Keep track of how much data we sent to each socket.
      peerBytesSent[i] += bytesSent;
 
 
      //Disconnect after sending more than 1KB od data.
      if(peerBytesSent[i] > 1024)
      {
       //Disconnect the socket.
       closesocket(peerSockets[i]);
       peerSockets[i] = NULL;
       peerBytesSent[i] = 0;
      }
     }
    }
 
    //Is the socket in an error state?
    if(FD_ISSET(peerSockets[i], &fdExcept))
    {
     //Disconnect the socket.
     closesocket(peerSockets[i]);
     peerSockets[i] = NULL;
     peerBytesSent[i] = 0;
    }
   }
  }
 
  Sleep(1); //Give the CPU some breathing time.
 }
 
 //---------------------------------------------------------
 
 //Stop listening.
 closesocket(listenSocket);
 
 if(WSACleanup() == SOCKET_ERROR)
 {
  printf("Failed to cleanup WinSock: %d\n",
   WSAGetLastError());
  return 1;
 }
 
 return 0;
}


Now clearly there are more to sockets than this post covers (such as non-blocking asynchronous sockets) but trust me, the above is easily 10 fold more than my first socket application.

Is this code snippet, product or advice warrantied against ill-effect and/or technical malaise? No. No it's not! Not expressed - Not implied - not at all.



Tags:
 C++    TCP/IP    Winsock  

Created by Josh Patterson on 2/8/2013, last modified by Josh Patterson on 2/8/2013

No comments currently exists for this page. Why don't you add one?
First Previous Next Last 

Login or signup to leave a comment.
 
Copyright © 2014 NetworkDLS.
All rights reserved.
 
Privacy Policy | Our Company | Contact