?
Solved

Debugging simple Winsock2 Client

Posted on 2003-03-16
3
Medium Priority
?
305 Views
Last Modified: 2013-12-03
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;
}


0
Comment
Question by:MellowD0c
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
3 Comments
 
LVL 49

Expert Comment

by:DanRollins
ID: 8150562
>>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
 

Author Comment

by:MellowD0c
ID: 8155937
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
 
LVL 49

Accepted Solution

by:
DanRollins earned 240 total points
ID: 8156139
>>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

Featured Post

Visualize your virtual and backup environments

Create well-organized and polished visualizations of your virtual and backup environments when planning VMware vSphere, Microsoft Hyper-V or Veeam deployments. It helps you to gain better visibility and valuable business insights.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article surveys and compares options for encoding and decoding base64 data.  It includes source code in C++ as well as examples of how to use standard Windows API functions for these tasks. We'll look at the algorithms — how encoding and decodi…
A theme is a collection of property settings that allow you to define the look of pages and controls, and then apply the look consistently across pages in an application. Themes can be made up of a set of elements: skins, style sheets, images, and o…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
How to fix incompatible JVM issue while installing Eclipse While installing Eclipse in windows, got one error like above and unable to proceed with the installation. This video describes how to successfully install Eclipse. How to solve incompa…

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question