[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

Networking

Posted on 2006-06-25
6
Medium Priority
?
353 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
[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
  • 4
  • 2
6 Comments
 
LVL 12

Accepted Solution

by:
rajeev_devin earned 2000 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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 

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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
Suggested Courses

650 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