Solved

Networking

Posted on 2006-06-25
6
339 Views
Last Modified: 2008-02-26
This question is for an expert who knows WINSOCK programming.

I have these four files, this is from the book MULTILPLAYRE GAME PROGRAMMING, so if this content isn't appropriate to be here, please delete my questions.

I compiled these files in Visual Studio.net 2005 ( you need ws2_32.lib included in project), then I opened cmd.exe,

and ran one,

connectiontest server 6000

opened another cmd.exe and ran,

connectiontest client 243.54.56.76(my ip address) 6000

THEN,

on the client side, the data, "TestData from client" is sent successfully,
but on the server side, the byte received is -1.

I used WSAGetLastError() function to see what was the error, and i get WSAECONNRESET 10054 in return.

I spent hours trying to debug, but i just cannot figure. Could anyone grab these source code and run them and tell me why this isn't working?

Thank you very much.

/////////////////////////////ConnectionTest.h/////////////////////////////////////////////////////////////
#include <iostream>

#include "SocketObject.h"

using namespace std;

void vServerConnection(int iListenPort);
void vClientConnection(char *szServerIP, int iServerListenPort);

void PrintHelp();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/////////////////////////////ConnectionTest.cpp/////////////////////////////////////////////////////////////
#include "ConnectionTest.h"

int main(int argc, char *argv[])
{
      if(argc == 3 && strcmp(argv[1], "server") == 0)
      {
            //if user selected server, listen on the given port
            //and assign connection to the second port number
            vServerConnection( atoi(argv[2]));
      }
      else if(argc == 4 && strcmp(argv[1], "client") == 0)
      {
            //user selected client: connect to given port and IP address
            vClientConnection(argv[2], atoi(argv[3]) );
      }
      else
      {
            PrintHelp();
            return 0;
      }

      return 1;
}

void vServerConnection(int iListenPort)
{
      SocketObject ServerSocketObject;
      SocketObject ClientSocketObject;
      char             DataPacket[128];            //Data packet to receive
      int                   iBytesReceived = 0;    //# of Bytes received

      cout<<"<Server> Attemption to listen on Port" << iListenPort <<endl;

      //Attempt to start the server on port 6000
      if(ServerSocketObject.Bind(iListenPort))
      {
            cout<<"<Server> Listening" <<endl;

            //Listen for conneciton on the listen port
            ServerSocketObject.Listen();

            //Accept the connection
            ServerSocketObject.Accept(ClientSocketObject);

            cout<<"<Server> Client Connected to Port" << iListenPort <<endl;

            //receive data
            iBytesReceived = ClientSocketObject.Recv(DataPacket, 128, 0);
            cout << "<Server> Received " << iBytesReceived << "Bytes" << endl;
            cout << "<Server> Data Received = " << DataPacket << endl;

            //Disconnect the client
            ClientSocketObject.Disconnect();

            cout<<"<Server> Client Disconnected" <<endl;
      }
      else
      {
            cout<<"<Server> Failed to listen" << endl;
      }
}

void vClientConnection(char *szServerIP, int iServerListenPort)
{
      SocketObject ClientSocketObject;
      char             DataPacket[128];      //Data Packet to transmit
      int                   iBytesSent = 0;      //# of bytes sent

      cout<<"<Client> connecting to " << szServerIP <<", Port" << iServerListenPort <<endl;

      //Connect to the IP and Port
      if(ClientSocketObject.Connect(szServerIP, iServerListenPort))
      {
            cout << "<Client> Connected" <<endl;

            //populate the data packet
            strcpy_s(DataPacket, "TestData from client");

            //Send Data
            iBytesSent = ClientSocketObject.  Send(DataPacket, 128, 0);

            cout << "<Server> Data Transmitted = " << DataPacket << endl;
            cout << "<Client> Transmitted " << iBytesSent << "Bytes" << endl;


            //Disconnect from the server
            ClientSocketObject.Disconnect();

            cout<<"<Client> Disconnected from Server" <<endl;
      }
      else
      {
            cout << "<Client> Failed to connect" <<endl;
      }
}

void PrintHelp()
{
      cout << "-------------------------------------------------" << endl;
      cout << "              ConnectionTest Help                " << endl;
      cout << "-------------------------------------------------" << endl;
      cout << "Usage: ConnectionTest [client/server] [ip, port/port, port]" << endl;
      cout << "" << endl;
      cout << "Example: ConnectionTest client 198.168.0.1 6000" << endl;
      cout << "" << endl;
      cout << "Example: ConnectionTest server 6000" << endl;
      cout << "" << endl;
}
//////////////////////////////////SocketObject.h//////////////////////////////////////////////////
//###################################################################################
//#                                                                                                                              #
//#                  Chapter 7 - Socket Object Class Definition                                                #            
//#                                                                                                                              #
//#                                    Class to Handle Client/Server Communication                              #
//#                                                                                                                              #
//#                                    Todd Barron, 08/06/2000                                                            #
//#                                                                                                                              #
//###################################################################################

#ifndef SOCKET_OBJECT

#define SOCKET_OBJECT

// Windows Sockets Include, Also need ws2_32.lib included in project
#include <winsock2.h>
#include <iostream>

using namespace std;

struct stPacketHeader
{
      int            iType;
      int            iLength;
      int            iID;
      int            iCheckSum;
      int            iSender;
};

struct SocketTransmissionStruct
{
      SOCKET            skSocket;
      char            szBuffer[64000];
      int                  iWritePos;
      int                  iReadPos;
      int                  iTerminate;
};

// Class Object
class SocketObject  
{
      private:

      public:
            SOCKET                                    skSocket;
            int                                          iStatus;
            SocketTransmissionStruct      stReceive;      
            SocketTransmissionStruct      stSend;      
            DWORD                                    dwReceiveHandle;
            DWORD                                    dwSendHandle;

            // Constructor
            SocketObject();
            // Desctrucot
            ~SocketObject();

            // Accept a client's request to connect
            bool Accept(SocketObject& skAcceptSocket);
            // Listen for clients to connect
            int Listen( void );
            // Open a server listening port
            int Bind(int iPort);
            // Close connection
            void Disconnect();
            // Connect to a server
            bool Connect(char* szServerAddress, int iPort);

            int Recv(char *szBuffer, int iBufLen, int iFlags);
            int Send(char *szBuffer, int iBufLen, int iFlags);

            // Misc Functions
            int iCalculateChecksum(stPacketHeader stHead);

            // Asynchronous Functions
            static void thrReceiveThread(SocketTransmissionStruct *rs);
            static void thrSendThread(SocketTransmissionStruct &rs);
            int vGetPacket(char *szbuffer);
};

#endif


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

////////////////////////////////////SocketObject.cpp/////////////////////////////////////////////////////////////////
//###################################################################################
//#                                                                                                                              #
//#                                    Socket Object Member Functions                                                #            
//#                                                                                                                              #
//#                                    Class to Handle Client/Server Communication                              #
//#                                                                                                                              #
//#                                    Todd Barron, 08/06/2000                                                            #
//#                                                                                                                              #
//###################################################################################

#include "SocketObject.h"

// Constructor
SocketObject::SocketObject()
{
      WSADATA wsaData;
      WORD      wVersionRequested;

      wVersionRequested = MAKEWORD( 2, 0 );

      skSocket = INVALID_SOCKET;
      iStatus = WSAStartup(wVersionRequested,&wsaData);
}

// Destructor
SocketObject::~SocketObject()
{
      CloseHandle(&dwReceiveHandle);
      Disconnect();
}

int SocketObject::vGetPacket(char *szbuffer)
{
      int                        iBytesReceived = 0;
      int                        iBytesWaiting = 0;
      stPacketHeader      stHeader;

      // Check if write pos moved
      if( stReceive.iWritePos != stReceive.iReadPos ) {
            //
            // Pull packet header from buffer
            //
            iBytesWaiting = (stReceive.iWritePos - stReceive.iReadPos);
            // Make sure a full size header is present
            if( iBytesWaiting < sizeof(stHeader) ) {
                  return(0);
            }
            // Copy the header in
            memcpy(&stHeader,&stReceive.szBuffer[stReceive.iReadPos],sizeof(stHeader));
            // Check the checksum
            if( ((stHeader.iType+stHeader.iLength+stHeader.iID)) != stHeader.iCheckSum ) {
                  // Skip the first bad byte in an attempt to find a good packet
                  stReceive.iReadPos++;
                  if( stReceive.iReadPos >= 64000 ) {
                        stReceive.iReadPos = 0;
                  }
                  // Try again for a good packet
                  vGetPacket(szbuffer);
            }
            else {
            }

            //
            // Pull the body of the packet according to the size
            //
            
            // Make sure enough data is waiting, if not leave and try again later
            if( (iBytesWaiting-sizeof(stHeader)) < (unsigned)stHeader.iLength ) {
                  return(0);
            }
            // Copy into the return buffer
            memcpy(szbuffer,&stHeader,sizeof(stHeader));
            memcpy(&szbuffer[sizeof(stHeader)],&stReceive.szBuffer[stReceive.iReadPos+sizeof(stHeader)],stHeader.iLength);

            // Update Read Position & Return Values
            stReceive.iReadPos += (stHeader.iLength+sizeof(stHeader));
            iBytesReceived = (stHeader.iLength+sizeof(stHeader));
            
            // Check if reading too far
            if( stReceive.iReadPos >= 64000 ) {
                  stReceive.iReadPos = 0;
            }
      }

      return(iBytesReceived);
}

void SocketObject::thrReceiveThread(SocketTransmissionStruct *rs)
{
      int                        iBytesReceived;
      char                  *szTempBuffer;
      int                        iBytesPart1;
      int                        iBytesPart2;

      szTempBuffer = new char[32768];

      // Receive data until given notice to terminate
      while( rs->iTerminate != 1 ) {
            // Read from the pipe
            iBytesReceived = recv( rs->skSocket, szTempBuffer, 32768, 0 );
            if( iBytesReceived > 0 ) {
                  // Make sure the packet does not overrun the write buffer
                  if( (rs->iWritePos+iBytesReceived) >= 64000 ) {
                        iBytesPart1 = ((rs->iWritePos+iBytesReceived)-64000);
                        iBytesPart2 = (64000 - rs->iWritePos);
                        memcpy( &rs->szBuffer[rs->iWritePos], szTempBuffer, iBytesPart1 );
                        memcpy( &rs->szBuffer[0], &szTempBuffer[iBytesPart1], iBytesPart2 );
                        rs->iWritePos = iBytesPart2;
                  }
                  else {
                        // Write to the permanent buffer
                        memcpy( &rs->szBuffer[rs->iWritePos], szTempBuffer, iBytesReceived );
                        rs->iWritePos += iBytesReceived;
                  }
            }
      }

      delete [] szTempBuffer;
}

void SocketObject::thrSendThread(SocketTransmissionStruct &rs)
{
      int iBytesSent;
      
      iBytesSent = send( rs.skSocket, rs.szBuffer, 128, 0 );
}

// Connect
bool SocketObject::Connect(char* szServerAddress, int iPort)
{
      struct            sockaddr_in serv_addr;
      LPHOSTENT      lphost;

      memset(&serv_addr,0,sizeof(sockaddr_in));
      serv_addr.sin_family = AF_INET;
      serv_addr.sin_addr.s_addr = inet_addr(szServerAddress);

      if (serv_addr.sin_addr.s_addr == INADDR_NONE)
      {
            lphost = gethostbyname(szServerAddress);
            if (lphost != NULL)
                  serv_addr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
            else
            {
                  WSASetLastError(WSAEINVAL);
                  return FALSE;
            }
      }

      serv_addr.sin_port = htons(iPort);

      // Open the socket
      skSocket = socket(AF_INET, SOCK_STREAM, 0);
      if(skSocket == INVALID_SOCKET)
      {
            return false;
      }

      int err = connect(skSocket, (struct sockaddr*)&serv_addr,sizeof(sockaddr));
      if(err == SOCKET_ERROR)
      {
            Disconnect();
            return false;
      }

      
      stReceive.skSocket = skSocket;
      stReceive.szBuffer[0] = NULL;
      stReceive.iReadPos = 0;
      stReceive.iWritePos = 0;
      stReceive.iTerminate = 0;

      // Create the thread to receive data
      CreateThread(
            NULL,  // pointer to security attributes
            NULL,                         // initial thread stack size
            (LPTHREAD_START_ROUTINE ) &thrReceiveThread,     // pointer to thread function
            &stReceive,                        // argument for new thread
            NULL,                     // creation flags
            &dwReceiveHandle          // pointer to receive thread ID
      );

      return true;
}

void SocketObject::Disconnect()
{
      if(skSocket != INVALID_SOCKET)
      {
            closesocket(skSocket);
            skSocket = INVALID_SOCKET;
      }
}

int SocketObject::Bind(int iPort)
{
      sockaddr_in saServerAddress;

      skSocket = socket(AF_INET, SOCK_STREAM, 0);
      
      if(skSocket == INVALID_SOCKET)
      {
            return false;
      }

      memset(&saServerAddress, 0, sizeof(sockaddr_in));

      saServerAddress.sin_family = AF_INET;
      saServerAddress.sin_addr.s_addr = htonl(INADDR_ANY);
      saServerAddress.sin_port = htons(iPort);

      if( bind(skSocket, (sockaddr*) &saServerAddress, sizeof(sockaddr)) == SOCKET_ERROR)
      {
            Disconnect();
            return false;
      }
      else
            return true;
}

int SocketObject::Listen( void )
{
      return listen( skSocket, 32 );
}

bool SocketObject::Accept( SocketObject &skAcceptSocket )
{
      sockaddr_in saClientAddress;
      int                  iClientSize = sizeof(sockaddr_in);
      SOCKADDR      IPAddress;

      skAcceptSocket.skSocket = accept( skSocket, (struct sockaddr*)&saClientAddress, &iClientSize );
      
      if( skAcceptSocket.skSocket == INVALID_SOCKET )
      {
            return false;
      }
      else
      {
            memcpy(&IPAddress,&saClientAddress,sizeof(saClientAddress));
            printf("%d.%d.%d.%d is Connecting\n",saClientAddress.sin_addr.S_un.S_un_b.s_b1,saClientAddress.sin_addr.S_un.S_un_b.s_b2,saClientAddress.sin_addr.S_un.S_un_b.s_b3,saClientAddress.sin_addr.S_un.S_un_b.s_b4);

            skAcceptSocket.stReceive.skSocket = skAcceptSocket.skSocket;
            skAcceptSocket.stReceive.szBuffer[0] = NULL;
            skAcceptSocket.stReceive.iReadPos = 0;
            skAcceptSocket.stReceive.iWritePos = 0;
            skAcceptSocket.stReceive.iTerminate = 0;
            
            // Create the thread to receive data
            CreateThread(
                  NULL,                                                                                          // pointer to security attributes
                  NULL,                                                                                          // initial thread stack size
                  (LPTHREAD_START_ROUTINE ) &skAcceptSocket.thrReceiveThread,     // pointer to thread function
                  &skAcceptSocket.stReceive,              // argument for new thread
                  NULL,                                                      // creation flags
                  &skAcceptSocket.dwReceiveHandle         // pointer to receive thread ID
            );

            return true;
      }
}

int SocketObject::Recv( char *szBuffer, int iBufLen, int iFlags)
{
      return recv(skSocket, szBuffer, iBufLen, iFlags);
}

int SocketObject::Send(char *szBuffer, int iBufLen, int iFlags)
{
      return send(skSocket,szBuffer,iBufLen,iFlags);
}

int SocketObject::iCalculateChecksum(stPacketHeader stHead)
{
      int      iChecksum = 0;

      iChecksum = (stHead.iID+stHead.iLength+stHead.iType);

      return(iChecksum);
}




////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
0
Comment
Question by:wonjun
  • 4
  • 2
6 Comments
 
LVL 12

Accepted Solution

by:
rajeev_devin earned 500 total points
ID: 16981119
You are reading data in receive thread also
void SocketObject::thrReceiveThread(SocketTransmissionStruct *rs)
0
 
LVL 12

Expert Comment

by:rajeev_devin
ID: 16981122
Also you are reading data in main thread through this function
 iBytesReceived = ClientSocketObject.Recv(DataPacket, 128, 0);
0
 
LVL 12

Expert Comment

by:rajeev_devin
ID: 16981124
You didn't even have taken any mutex for synchronization.
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 

Author Comment

by:wonjun
ID: 16981524
so how should i change the code to make it work? i'm quite lost.
Thank you.
0
 

Author Comment

by:wonjun
ID: 16981782
OHHH i get it thank you ver ymuch,....those receive thread outside of main aren't supposed to be there, but the bookis so poorly organized and i didn even notice it got in there!!!

thank you for pointing that out. that was exactly what i forgot to look for..
0
 
LVL 12

Expert Comment

by:rajeev_devin
ID: 16981835
My pleasure :)
0

Featured Post

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

708 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now