//  soc.cpp

#include "stdafx.h"
#include "soc.h"
#include "winsock2.h"

/******************************************************
*                                                     *
*      ECHO Client  (gennaio 2001)                    *
*                                                     *
*      legge una sringa (puo' contenere anche blank)  *
*      dall'input. Invia al server il numero di       *
*      caratteri (intero 4 byte) e poi la stringa.    *
*                                                     *
*      Per cambiare l'host del server, modificare     *
*      la macro HOSTNAME.                             *
*                                                     *
*      La porta e' 3123, protocollo TCP/IP            *
*                                                     *
*      Linkare con ws2_32.lib                         *
*                                                     *
*******************************************************/

#define PORTNUM         3123          // Port number
#define HOSTNAME        "localhost"   // Server name string
                                      // These values should be changed
                                      // ... according to the server

void recvn (SOCKET LocalSock, char *ptr, int nbytes);
void sendn (SOCKET LocalSock, char *ptr, int nbytes);
char *  Alloc(SOCKET LocalSock, int len);
void printError(SOCKET LocalSock, int error);

CWinApp theApp;

using namespace std;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
  const int MAXMSG=100;
  char msg[MAXMSG];
  int len;
  char szError[100];

  SOCKET ServerSock = INVALID_SOCKET; // Socket bound to the server
  SOCKADDR_IN destination_sin;        // Server socket address
  PHOSTENT phostent = NULL;           // Points to the HOSTENT structure
                                              // ... of the server
  WSADATA WSAData;          

        // initialize MFC and print and error on failure
        if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
          {
        cerr << _T("Fatal Error: MFC initialization failed") << endl;
                exit(1);
          }

        // Initiate Windows Sockets. 
        if (WSAStartup (MAKEWORD(1,1), &WSAData) != 0) 
        {
     wsprintf(szError, "WSAStartup failed. Error: %d ", 
                      WSAGetLastError ());
     MessageBox (NULL, szError, TEXT("Error"), MB_OK);
     WSACleanup ();
     exit(1);
    }

        // Create a TCP/IP socket that is bound to the server.
        if ((ServerSock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
        {
      wsprintf (szError, "Allocating socket failed. Error: %d",
                        WSAGetLastError ());
      MessageBox (NULL, szError, TEXT("Error"), MB_OK);
      WSACleanup ();
      exit(1);
     }

      // Fill out the server socket's address information.
      destination_sin.sin_family = AF_INET;

      // Retrieve the host information corresponding to the host name.
      if ((phostent = gethostbyname (HOSTNAME)) == NULL) 
       {
         wsprintf (szError, "Unable to get the host name. Error: %d", 
                       WSAGetLastError ());
         MessageBox (NULL, szError, TEXT("Error"), MB_OK);
         closesocket (ServerSock);
         WSACleanup ();
         exit(1);
        }

      // Assign the socket IP address.
      memcpy ((char FAR *)&(destination_sin.sin_addr), 
                phostent->h_addr, 
                phostent->h_length);

        // Convert to network ordering.
        destination_sin.sin_port = htons (PORTNUM);      

        // Establish a connection to the server socket.
        if (connect (ServerSock, (PSOCKADDR) &destination_sin, 
               sizeof (destination_sin)) == SOCKET_ERROR) 
      {
       wsprintf (szError, 
         "Connecting to the server failed. Error: %d",
          WSAGetLastError ());
       MessageBox (NULL, szError, TEXT("Error"), MB_OK);
       closesocket (ServerSock);
       WSACleanup ();
       exit(1);
      }

     printf("messaggio da inviare (<%d chars) > ", MAXMSG);
     cin.getline(msg, sizeof(msg),'\n');
     len=strlen(msg);
         sendn (ServerSock, (char *) &len, 4);
     sendn (ServerSock, msg, len);
     recvn(ServerSock, (char*) &len, 4);
         if (len<100) 
         {
                 recvn(ServerSock, msg, len);
                 printf("ricevuto %s \n", msg);
         }
         else
     {
      wsprintf(szError, "Connecting to the server failed. Error: %d",
          WSAGetLastError ());
       MessageBox (NULL, szError, TEXT("Error"), MB_OK);
         }
     closesocket (ServerSock);
     WSACleanup ();
     return TRUE;
}


/* this function sends exactly nbytes bytes or close conn. */
void sendn (SOCKET LocalSock, char *ptr, int nbytes)
 {
  int   nleft, nwritten;
  nleft = nbytes;
  int WSAerr;

  while (nleft > 0)
   {
    nwritten = send (LocalSock, ptr, nleft, 0);
    if (nwritten == SOCKET_ERROR)   
     {
       WSAerr=WSAGetLastError ();
       cerr << _T("Sending data to the server failed. Error: ") 
            << WSAerr << endl;  
       closesocket(LocalSock);
       WSACleanup ();
       exit(1);
     }
    nleft -= nwritten;
    ptr += nwritten;
   }
  return;
}


/* this function recvs exactly nbytes bytes or close conn. */
void recvn (SOCKET LocalSock, char *ptr, int nbytes)
 {
  int   nleft, nrecv;
  int WSAerr;  
  nleft = nbytes;

  while (nleft > 0)
   {
    nrecv = recv (LocalSock, ptr, nleft, 0);
    if (nrecv == SOCKET_ERROR)
    {
     WSAerr=WSAGetLastError ();
     cerr << _T("recv failed.  Error: ") << WSAerr << endl;  
     closesocket(LocalSock);
     WSACleanup ();
     exit(1);
    }
    if (nrecv == 0)
    {
      cerr << _T("Connection has been lost on recv ") << endl; 
      closesocket(LocalSock);
      WSACleanup ();
      exit(1);
    }
    nleft -= nrecv; 
    ptr += nrecv;
   }
  return;
}