Debugging simple Winsock2 Client

Here is what i have for the client so far. How can i extract the port # off the commandline? The way i am doing this is what i have seen in most examples online, but somehow it gives me error. Also i saw in many places that are using:

int main(int argc, char **argv) instead of int main(int argc, char *argv)

a '**' to argv, and i am wondering what it does? If i use just one pointer it gives me this error:

client.cpp(40): error C2664: 'atoi' : cannot convert parameter 1 from 'char' to 'const char *'
        Conversion from integral type to pointer type requires reinterpret_cast, C-style cast or function-style cast


Second Question:

If i compile the below code, it gives me this error while/after Linking, and how could i fix it?

Unhandled exception at 0x00467b99 in CSsock.exe: 0xC0000005: Access violation reading location 0x00000000.

and it points to atox.c file (i believe this has to do with my atoi(port) converter.

All i want from this client is to be able to just connect to server by the mentioned port on the commandline, send messages  and recieve them as well. More like really simple chat client.


//
// client.cpp


#include <stdio.h>
#include <iostream>
#include <winsock2.h>
#include <conio.h>

#define HOSTNAMELEN 128


using namespace std;

////////////////////////////////////////////////////////////

int main(int argc, char **argv)
{
      
      
      struct hostent *host;
      char buffer[100];
      int result;
      if (argc > 1 )
      {
            
            cerr << "Syntax: server PortNumber" <<endl;
            exit (1);
      }
      
      
      WORD wVersionRequested = MAKEWORD(2,2);
      WSADATA wsaData;
      if(WSAStartup(wVersionRequested, &wsaData)!=0)
      {
            cerr << "Process failed on Winsock startup" << endl;
            ExitProcess(0);
      }

      int Port = atoi(argv[1]);
      SOCKADDR_IN theSrvr;
      char serverHostName[HOSTNAMELEN];
      result = gethostname(serverHostName, HOSTNAMELEN);
      
      host = gethostbyname(serverHostName);
      if (result == SOCKET_ERROR)
      {
            result = WSAGetLastError();
            cerr << "Error Occured  " << result << endl;
                  exit (1);
      }
      
      
      ZeroMemory(&theSrvr, sizeof(SOCKADDR_IN));
      theSrvr.sin_family = AF_INET;
      theSrvr.sin_port = htons((u_short)Port);
      
      CopyMemory(&theSrvr.sin_addr, host->h_addr_list[0], host->h_length);


      SOCKET skt = socket(AF_INET, SOCK_STREAM, 0);
      if (skt == INVALID_SOCKET)
      {
            result = WSAGetLastError();
            cerr << "Error Occured  " << result << endl;
            WSACleanup();
            exit (1);
      }
  int len = sizeof(theSrvr);
      getsockname(skt, (SOCKADDR *) &theSrvr, &len);
      u_short actual_port = ntohs(theSrvr.sin_port);
      //
      //connect
      //
      result = connect(skt, (const SOCKADDR *) &theSrvr, sizeof(theSrvr));
      
      if (result == SOCKET_ERROR)
      {
            result = WSAGetLastError();
            cerr << "Error Occured  " << result << endl;
            closesocket(skt);
            exit (1);
      }

      


      //
      // Find the server
      //
   // LPHOSTENT lpHostEntry;

//      lpHostEntry = gethostbyname(theSrvr);
   
      // Show the port number
      //
      cout <<"============================================================="<<endl;
      cout <<"============================================================="<<endl;
      cout <<"======================TALK Client============================"<<endl;
      cout <<"============Connecting on Port: " << Port << endl;
      cout <<"============================================================="<<endl;
      cout <<"============================================================="<<endl;
      

SOCKET remoteSocket;
while (true)
 {
       memset(buffer, 0, sizeof(buffer));
            if(_kbhit()){
                        int bytesRead = send(remoteSocket, buffer, sizeof(buffer), 0);


                        if (-1 == bytesRead)
                              {
                              cout << "Socket Error" << endl;
                              break;
                              }
                        else if (0 == bytesRead)
                              {
                              cout << "Socket closed on other side" << endl;
                              break;
                              }
                        else
                              {
                              buffer[bytesRead] = '\0';
                              cout << "<" << buffer << endl;
                              recv(remoteSocket, buffer, sizeof(buffer)-1, 0);
                        Sleep(500);
                              }
            }
  }
      //
      // Close BOTH sockets before exiting
      //
      closesocket(remoteSocket);
      closesocket(skt);
      

      //
      // Release WinSock
      //
      WSACleanup();
return 0;
}


MellowD0cAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

DanRollinsCommented:
>>int main(int argc, char **argv)

argv is a char** (pointer to a character pointer).  It is more often expressed as:

    int main(int argc, char* argv[])

which is the same thing, but is more easily read as "an array of pointers to char" or "an array of C-style strings".

Anyway, all it means is that you can cycle through each of the command-line arguments as follows:

for (int j=0; j< argc, j++ ) {
     printf("parm %d is %s", j, argv[j] );
     if ( strcmp(argv[j],"/DELETE") == 0 ) {
         // recieved a parameter of /DELETE
         // so take notice!
     }
}
-==-=-=-=-=-=-=-=-=-=-=-
as to the error... you are not verifying that there is a valid argv[1] before calling atoi.  Use code like:

if (argc > 1) {  // argv[0] and argv[1] are valid
     printf("parm 1 is %s", argv[1] );
}

-- Dan
0
MellowD0cAuthor Commented:
Thanks, I modified that part, but appears to me that my send() and recv() functions aren't working. My client does connect but it disconnects after establishing a successful connection. Can you tell what am i doing wrong in the following code? I want to make it send and receive messages and exit only if someone types exit in the start of line....

//
// Client.cpp


#include <stdio.h>
#include <iostream>
#include <winsock2.h>
#include <conio.h>

#define HOSTNAMELEN 128


using namespace std;

////////////////////////////////////////////////////////////

int main(int argc, char *argv[])
{
      
      
      struct hostent *host;
      char buffer[1024];// for send()
      char xbuffer[1024];      // for recv()
          
      int result;
      int Port=0;

      while (--argc)
      {
            if (argc == 1)
            {
                  Port = atoi(argv[1]);
            }
            if (argc > 2 )
            {
                        
                  cerr << "Syntax: server PortNumber" <<endl;
                        exit (1);
            }
      }
      //Set Winsock Version #
      WORD wVersionRequested = MAKEWORD(2,2);
      WSADATA wsaData;
      if(WSAStartup(wVersionRequested, &wsaData)!=0)
      {
            cerr << "Process failed on Winsock startup" << endl;
            ExitProcess(0);
      }

      
      SOCKADDR_IN theSrvr;
      char serverHostName[HOSTNAMELEN];
      result = gethostname(serverHostName, HOSTNAMELEN);
      //
      // Find the server
      //
   
      host = gethostbyname(serverHostName);
      if (host == NULL) {
            cerr << " Error Occured: " << WSACleanup() <<endl;
                        
                  }

      
      
      ZeroMemory(&theSrvr, sizeof(SOCKADDR_IN));
      theSrvr.sin_family = AF_INET;
      theSrvr.sin_port = htons((u_short)Port);
      
      CopyMemory(&theSrvr.sin_addr, host->h_addr_list[0], host->h_length);


      SOCKET skt = socket(AF_INET, SOCK_STREAM, 0);
      if (skt == INVALID_SOCKET)
      {
            result = WSAGetLastError();
            cerr << "Error Occured  while making Socket " << result << endl;
            WSACleanup();
            exit (1);
      }
      //SOCKET remoteSocket;
  int len = sizeof(theSrvr);
      getsockname(skt, (SOCKADDR *) &theSrvr, &len);
      u_short actual_port = ntohs(theSrvr.sin_port);
      //
      //connect
      //
      result = connect(skt, (const SOCKADDR *) &theSrvr, sizeof(theSrvr));
      
      if (result == SOCKET_ERROR)
      {
            result = WSAGetLastError();
            cerr << "Error Occured while connection  " << result << endl;
            closesocket(skt);
            exit (1);
      }

      
   
      // Show the port number
      //
      cout <<"============================================================="<<endl;
      cout <<"============================================================="<<endl;
      cout <<"======================TALK Client============================"<<endl;
      cout <<"============Connecting on Port: " << Port << endl;
      cout <<"============================================================="<<endl;
      cout <<"============================================================="<<endl;
      


while (true)
{
       memset(buffer, 0, sizeof(buffer));
            if(_kbhit())
            {
                        int bytesRead = send(skt, buffer, sizeof(buffer), 0);

                        if (-1 == bytesRead)
                              {
                              cout << "Socket Error" << endl;
                              break;
                              }
                        else if (0 == bytesRead)
                              {
                              cout << "Socket closed on other side" << endl;
                              break;
                              }
                        else
                              {
                              buffer[bytesRead] = '\0';
                              cout << "<" << buffer << endl;
                              recv(skt, xbuffer, sizeof(xbuffer)-1, 0);
                              cout << ">" << xbuffer << endl;
                              memset(xbuffer, 0, sizeof(xbuffer));
                        Sleep(500);
                              }
            }
}
      closesocket(skt);
      // Release WinSock
      WSACleanup();
return 0;
}
0
DanRollinsCommented:
>>I want to make it send and receive messages and exit only if someone types exit in the start of line....

You need to plan what you want to do and then do it.  The code that's there simply doesn't do anything like what you say you want it to do.  For instance, pretend to be a computer and see what will happen the first time though the while loop.

1) clear the buffer to all zeros
2) if there has been a kestroke..
3)     send 1024 bytes of 0 to the host
4)     detect error
5)     display a misleading message
6)     skip the else because it can't happen
7)     Do nothing for 1/2 second
8) go back to step one and repeat

First, please read up on the send() function, you'll see that it is not used to receive data from the remote host.  That would be a start.

Next, remove the kbhit() and the while loop.  Just do some simple tests.  Send a string, and then use Sleep to wait a few seconds and use recv() to read the first few bytes of whatever the host has sent.

Use the debugger to single-step through the code, and be sure to examine variables in the variable window.

-- Dan
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Microsoft Development

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.