c++ socket server - WSAEISCONN 10056 error

Hi,

I have created an app that communicates via tcp sockets. The socket isn't asynchronous (This suits my needs) and I'm receiving the error when trying to invoke listen() on the server after one successful call.

can anybody see why this is occurring?

socket.h:
#pragma once //Only process header files once
#pragma comment(lib, "WS2_32.lib") //Add "WS2_32.lib" as a linker input
#include <iostream> //Input/output stream
#include "WinSock2.h" //Include WinSock
 
using namespace std; //Standard namespace
 
const int STRLEN = 1024; //Max length of our messages
 
class Socket //Socket base class
{
    protected:
        WSADATA wsaData; //wsaData
        SOCKET mySocket; //Socket
        SOCKET myBackup; //Socket
        SOCKET acceptSocket; //Socket
        sockaddr_in myAddress; //Socket Address
    public:
        Socket(); //"Prototype" constructor<
        ~Socket(); //"Prototype" destructor
        bool SendData( char* ); //"Prototype" SendData
        bool RecvData( char*, int ); //"Prototype" RecvData
        void CloseConnection(); //"Prototype" CloseConnection
        void GetAndSendMessage(); //"Prototype" GetAndSendMessage
}; //End base class
 
class ServerSocket : public Socket //Create our server socket class (derived)
{
    public:
        void Listen(); //"Prototype" Listen
        void Bind( int port ); //"Prototype" Bind
        void StartHosting( int port ); //"Prototype" StartHosting
}; //End ServerSocket class
 
class ClientSocket : public Socket //Create our client socket class (derived)
{
    public:
        void ConnectToServer( const char *ipAddress, int port ); //"Prototype" ConnectToServer
};

Open in new window


Socket impl:
#include "stdafx.h"
#include "Socket.h"
 
Socket::Socket() //Constructor
{
    if( WSAStartup( MAKEWORD(2, 2), &wsaData ) != NO_ERROR ) //WsaStartup
    {
        cerr<<"Socket Initialization: Error with WSAStartup\n"+WSAGetLastError(); //Error
        system("pause"); //Pause the program
        WSACleanup(); //Clean up
        exit(10); //Exit
    }
 
    //Create a socket
    mySocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); //Set our socket variable
 
    if ( mySocket == INVALID_SOCKET ) //If the socket didn't set correctly
    {
        cerr<<"Socket Initialization: Error creating socket"+WSAGetLastError()<<endl; //Error
        system("pause"); //Pause the program
        WSACleanup(); //Clean up
        exit(11); //Exit
    }
 
    myBackup = mySocket; //Set the backup socket to the socket
}
 
Socket::~Socket() //Destructor
{
    WSACleanup(); //Clean up
}
 
bool Socket::SendData( char *buffer ) //SendData
{
    send( mySocket, buffer, strlen( buffer ), 0 ); //Send the data
    return true; //Return true
}
 
bool Socket::RecvData( char *buffer, int size ) //RecvData
{
    int i = recv( mySocket, buffer, size, 0 );
    buffer[i] = '\0';
    return true;
}
 
void Socket::CloseConnection()
{
    //cout<<"==CLOSE CONNECTION=="<<endl;
    closesocket( mySocket ); //Close the socket
    mySocket = myBackup; //Set the socket to the backup
}
 
void Socket::GetAndSendMessage() //GetAndSendMessage
{
    char message[STRLEN];//Char array
    cin.ignore();//Without this it uses the return char from last cin and passes this one!
    cout<<"> ";
    cin.get( message, STRLEN ); //Get the message
    SendData( message ); //Send the data
}
 
void ServerSocket::StartHosting( int port ) //StartHosting (for our ServerSocket class)
{
     Bind( port ); //Bind to the port
     Listen(); //Listen for connection attempts
}
 
void ServerSocket::Listen() //Listen (for our ServerSocket class)
{
    //cout<<"LISTEN FOR CLIENT..."<<endl;
 
    if ( listen ( mySocket, 1 ) == SOCKET_ERROR ) //If there is a problem
    {
		 int i = WSAGetLastError();
        cerr<<"ServerSocket: Error listening on socket\n"+WSAGetLastError(); //Error
        system("pause"); //Pause the program
        WSACleanup(); //Clean up
        exit(15); //Exit
    }
 
    //cout<<"==ACCEPT CONNECTION=="<<endl;
 
    acceptSocket = accept( myBackup, NULL, NULL ); //Attempt to accept connection
    while ( acceptSocket == SOCKET_ERROR ) //While there is a problem
    {
        acceptSocket = accept( myBackup, NULL, NULL ); //Try to accept
    }
    mySocket = acceptSocket; //Set mySocket to acceptSocket
}
 
void ServerSocket::Bind( int port ) //Bind (for our ServerSocket class)
{
    myAddress.sin_family = AF_INET; //sin_family is always supposed to be AF_INET
    myAddress.sin_addr.s_addr = inet_addr( "0.0.0.0" ); //IP it connects to (dont need for server)
    myAddress.sin_port = htons( port ); //The port
 
    //cout<<"==BIND TO PORT=="<<port<<endl;
 
    if ( bind ( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress) ) == SOCKET_ERROR ) //If there is a problem
    {
        cerr<<"ServerSocket: Failed to connect\n"+WSAGetLastError(); //Error
        system("pause"); //Pause the program
        WSACleanup(); //Clean up
        exit(14); //Exit
    }
}
 
void ClientSocket::ConnectToServer( const char *ipAddress, int port ) //ConnectToServer (for our ClientSocket class)
{
    myAddress.sin_family = AF_INET; //sin_family is always supposed to be AF_INET
    myAddress.sin_addr.s_addr = inet_addr( ipAddress ); //IP it connects to
    myAddress.sin_port = htons( port ); //The port
 
    //cout<<"==CONNECTED=="<<endl;
 
    if ( connect( mySocket, (SOCKADDR*) &myAddress, sizeof( myAddress ) ) == SOCKET_ERROR ) //If there is a problem
    {
        cerr<<"ClientSocket: Failed to connect\n"+WSAGetLastError(); //Error
        system("pause"); //Pause the program
        WSACleanup(); //Clean up
        exit(13); //Exit
    }
}

Open in new window


SocketServer class
#include "stdafx.h"
#include "SocketServer.h"
#include <vector>
#include <iterator>

bool NFLSocketServer::run()
{
	cout<<"==HOSTING=="<<endl; //Tell the user we are hosting
    //sockServer.StartHosting( port ); //StartHosting

	sockServer.Bind(this->port);

	this->done = false;
	//Connected
	bool connected = false;


	while ( !done )
	{
		cout << "Listening for connections..." << endl;

		sockServer.Listen();

		connected = true;

		while(connected)
		{
			//initialise buffer
			//vector<string> buffer;
			string accum;
			bool filling = true;
			//fill the buffer
			while(filling)
			{
				cout << "-------- READ ---------" << endl;
				//read off socket
				sockServer.RecvData( recMessage, STRLEN ); //Receive data
       
				string msg(recMessage);
				cout << msg << endl;
				Message::trim(msg);
				accum += msg + " ";


				if(accum.size() > 0 && accum.find(" end ")!= string::npos )
				{
					filling = false;
				}
			}


			vector<string> buffer = Message::split(accum);
			
			
			if(buffer.size() > 0 )
			{
				//buffer.back().compare("end")==0
				int backIndex = buffer.size()-1;
				while(buffer[backIndex].compare("")==0 && backIndex >=0)
				{
					backIndex--;
				}

				if(buffer[backIndex].compare("end")==0)
				{
					cout << "Buffer filled" << endl;
					this->process(buffer);
				}
				else 
				{
					cout << "invalid buffer. " << endl;
				}
			}
			else 
			{
				cout << "invalid buffer. " << endl;
			}
		
			connected = false;
		}
	}
	return done;
}

bool NFLSocketServer::process(vector<string> data)
{
	//internal logic, i dont think this affects server execution

	return success;
}

void NFLSocketServer::setIPAddress(string ip)
{
	this->ipAddress = ip;
}

void NFLSocketServer::setPort(int portNum)
{
	this->port = portNum;
}


}

Open in new window



An exception is thrown on this line: sockServer.Listen(); after one call has been processed.

Any help appreciated
basil365Asked:
Who is Participating?
 
mccarlConnect With a Mentor IT Business Systems Analyst / Software DeveloperCommented:
The problem would be because you are calling listen() on the socket that is already listening. The listen() call should only be made once, it is the accept() call that is made after the server has served each client. General outline in pseudocode is...


listen(serverSocket);

while(true) {
   socket = accept(serverSocket);

   recv(socket, ...);
   send(socket, ...);
   send(socket, ...);
   // etc, etc

   close(socket);
}

Also, note that there are two distinct sockets in the above. The 'serverSocket' that represents the socket that is listening for connections from clients, and there is only one of these and it stays the same for the whole duration while your server is running. Then there is the 'socket' which represents just the individual connection to a particular client. There ends up being many of these, one for each client connection that has come in to your server. In your code, while it may eventually work, you might also want to change things around to make this distinction, rather than what you have now with mySocket, myBackup, acceptSocket, etc.
0
 
OrcbighterConnect With a Mentor Commented:
I have spotted  a few problems here:
1. Only call WSACleanup if you have previously successfully called WSAStartup, not after failing a call to WSAStartup. The easiest way to do this is to add a boolean member variable to your Socket class (say m_bInitialised). If you successfully call WSAStartup then set it to true.
Then in your destructor test if the boolean is true before calling WSACleanup.
NOTE: be sure to close the socket first in the destructor before calling WSACleanup.

2: You should initialise your Socket member variables in the Socket constructor before using them, eg:
Class Socket
  : mySocket( NULL ),
    myBackup( NULL ),
    acceptSocket( NULL ),
    m_bInitialised( false )
{
    SecureZeroMemory( &myAddress, sizeof( sockaddr_in ));
    SecureZeroMemory( &wsaData, sizeof( WSADATA ));

    ...
}

3: Unless you want to use exceptions, I would not initialise and create the socket in the class constructor.
If something fails in the constructor you have no way of knowing what really broke.
I would create a public method (called for example, Initialise() or Enable() returning a boolean.
In this way, you can capture any errors much easier, eg:

bool Socket::Initialise()
{
    bool retStatus = true;
   
    // call WSAStartup, set status to false on error
   
    // if OK, create socket, return false on error
    // do any other initialising stuff
    return retStatus;
}

in your server class

...
   bool bCallStatus = true;
  Socket sockServer;
 
  if ( !sockServer.Initialise() )
  {
    // handle error
  }
  else
  {
       bCallStatus = sockServer.Bind( this->port );   // modify this to return a status
       // any errors and cleanup will be handled by the Socket destructor, no need to keep erroneously calling WSACleanup
       ... etc
  }

  4.  mccarl is correct about the listen call.
  You should remove the accept(..) call from the Listen method of the Socket class (which should only be called once at the beginning of your program, after initialising the socket class) and place it in its own method.
  In fact, you could create a static method in the SocketServer class and pass it as a thread process into its own thread, and use the this pointer of the SocketServer class as a thread parameter. This static method could then call the Socket::OnAccept() method, in which the accept call is made. In this way your server class could handle many client threads.
0
 
basil365Author Commented:
Thanks for your help guys - i'll follow your points and clean it up a bit.
0
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.

All Courses

From novice to tech pro — start learning today.