Thread: TCP Server on Linux + boost

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    69

    TCP Server on Linux + boost

    Hey, Im writing small TCP server on Linux (first time). I'm using boost lib. And the code which was working on Windows isnt on Linux. I'm compiling using g++. Here is the source (btw any advices about structure, classes, performance from experienced coders welcome ).

    Code:
    #include "share.h"
    
    struct sockaddr_in serv_addr, cli_addr;
    
    class Client 
    {
    	private:
    		int ID, sock;
    		struct sockaddr_in clientinfo;
    	public:
    		boost::thread thread;
    		Client(){};
    		~Client(){};
    		void SetSock(int sock){this->sock = sock;}
    		void SetCInfo(struct sockaddr_in clientinfo){this->clientinfo = clientinfo;}
    		int GetID(){return this->ID;}
    		void SetID(int id){this->ID = id;}
    		bool ValidSock(){if (this->sock < 0) return 0; else return 1;}
    };
    
    class ClientHandler
    {
          private:
    		boost::thread ListenThread;
    		vector<Client> Clients;
          public:
             ClientHandler();
             ~ClientHandler(){}
    		 int ServeClient(int ID);
             int WaitClients(int ok);
             bool StartListen();
    };
    
    ClientHandler CHandler;
    
    class NetworkHandler
    {
    	private:
    		bool shutdown;
    		bool InitSocket()
    		{
    			ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
    			if (ListenSocket < 0) 
    			{
    				printf("NetworkHandler::InitSocket()::Error\n");
    				return 0;
    			}
    			printf("NetworkHandler::InitSocket()\n");
    			return 1;
    		};
    		bool BindSocket(int port)
    		{
    			bzero((char *) &serv_addr, sizeof(serv_addr));
    			serv_addr.sin_family = AF_INET;
    			serv_addr.sin_addr.s_addr = INADDR_ANY;
    			serv_addr.sin_port = htons(port);
    			if (bind(ListenSocket, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    			{
    				printf("NetworkHandler::BindSocket()::Error\n");
    				return 0;
    			}
    			printf("NetworkHandler::InitSocket()\n");
    			return 1;
    		};
    		bool StartListen()
    		{
    			if (listen(ListenSocket, SOMAXCONN) < 0)
    			{
    				printf("NetworkHandler::StartListen()::Error\n");
    				return 0;
    			}
    			printf("NetworkHandler::StartListen()\n");
    			return 1;
    		};
    	public:
    		int ListenSocket;
    		NetworkHandler(){};
    		~NetworkHandler(){};
    		bool StartServer(int port)
    		{
    			printf("NetworkHandler::StartServer(PORT %d)\n", port);
    			if (!InitSocket()) return 0;
    			if (!BindSocket(port)) return 0;
    			if (!StartListen()) return 0;
    			printf("NetworkHandler::ServerStatus -> Working!\n");
    			CHandler.StartListen();
    			return 1;
    		};
    		bool isShutDown(){return this->shutdown;}
    		void SetShutDown(bool shut){this->shutdown = shut;}
    };
    
    NetworkHandler NHandler;
    
    bool ClientHandler::StartListen()
    {
    	printf("ClientHandler::Initialize\n");
    	if (NHandler.ListenSocket >= 0)
    	{
    		boost::thread thread(&ClientHandler::WaitClients, CHandler, 0);
    		ListenThread = std::move(thread);
    	} else {
    		printf("ClientHandler::Listener::StartListen()::Error\n");
    		return 0;
    	}
    	return 1;
    }
    
    int ClientHandler::WaitClients(int ok)
    {
    	printf("ClientHandler::Listener::StartListen()\n");
    	do
    	{
    		int NewSock = -1;
    		struct sockaddr_in cinfo;
    		int cilen = sizeof(struct sockaddr);
    		if (NHandler.ListenSocket < 0)
    		{
    			printf("ClientHandler::ListenSocket::Closed!\n");
    			printf("ClientHandler::WaitClients::ExitThread\n");
    			ExitThread(0);
    		}
    		Client tmp;
    		tmp.SetSock(accept(NHandler.ListenSocket, (LPSOCKADDR)&cinfo, &cilen));
    		if (!tmp.ValidSock)
    		{
    			if(!NHandler.isShutDown()) printf("ClientHandler::NewConnection::Failed!\n");
    		} else {
    			tmp.SetCInfo(cinfo);
    			printf("ClientHandler::NewConnection::Connected from %s\n", inet_ntoa(cinfo.sin_addr));
    			boost::thread thread(&ClientHandler::ServeClient, CHandler, Clients.Size()+1);
    			tmp.thread = std::move(thread);
    		}
    	} while (!NHandler.isShutDown());
      return 0;
    }	 
    
    int ClientHandler::ServeClient(int ID)
    {
    //
    }
    
    int main()
    {	
    	if (!NHandler.StartServer(8383))
    	{
    		printf("NetworkHandler::ServerStatus -> Failed to Initialize!\n");
    		return 1;
    	}
    	return 0;
    }
    Errors :

    Code:
    server.cpp:26: error: ISO C++ forbids declaration of âvectorâ with no type
    server.cpp:26: error: expected â;â before â<â token
    /usr/include/boost/thread/detail/thread.hpp: In copy constructor âClientHandler::ClientHandler(ClientHandler&)â:
    /usr/include/boost/thread/detail/thread.hpp:108: error: âboost::thread::thread(boost::thread&)â is private
    server.cpp:23: error: within this context
    server.cpp: In member function âbool ClientHandler::StartListen()â:
    server.cpp:101: note: synthesized method âClientHandler::ClientHandler(ClientHandler&)â first required here
    server.cpp:101: error:   initializing argument 2 of âboost::thread::thread(F, A1, A2) [with F = int (ClientHandler::*)(int), A1 = ClientHandler, A2 = int]â
    server.cpp: In member function âint ClientHandler::WaitClients(int)â:
    server.cpp:122: error: âExitThreadâ was not declared in this scope
    server.cpp:125: error: âLPSOCKADDRâ was not declared in this scope
    server.cpp:126: error: could not convert âtmp.Client::ValidSockâ to âboolâ
    server.cpp:126: error: in argument to unary !
    server.cpp:131: error: âinet_ntoaâ was not declared in this scope
    server.cpp:132: error: âClientsâ was not declared in this scope
    In file included from /usr/include/boost/bind/bind.hpp:1596,
                     from /usr/include/boost/bind.hpp:22,
                     from /usr/include/boost/thread/detail/thread.hpp:20,
                     from /usr/include/boost/thread/thread.hpp:22,
                     from share.h:4,
                     from server.cpp:2:
    /usr/include/boost/bind/bind_mf2_cc.hpp: In function âboost::_bi::bind_t<Rt2, boost::_mfi::mf1<R, T, B1>, typename boost::_bi::list_av_2<A1, A2>::type> boost::bind(boost::type<R>, R (T::*)(B1), A1, A2) [with Rt2 = void, R = int, T = ClientHandler, B1 = int, A1 = ClientHandler, A2 = int]â:
    /usr/include/boost/thread/detail/thread.hpp:243:   instantiated from âboost::thread::thread(F, A1, A2) [with F = int (ClientHandler::*)(int), A1 = ClientHandler, A2 = int]â
    server.cpp:101:   instantiated from here
    /usr/include/boost/bind/bind_mf2_cc.hpp:48: error: no matching function for call to âboost::_bi::value<ClientHandler>::value(boost::_bi::value<ClientHandler>)â
    /usr/include/boost/bind/bind.hpp:116: note: candidates are: boost::_bi::value<T>::value(const T&) [with T = ClientHandler]
    /usr/include/boost/bind/bind.hpp:113: note:                 boost::_bi::value<ClientHandler>::value(boost::_bi::value<ClientHandler>&)
    /usr/include/boost/bind/bind_mf2_cc.hpp:48: error:   initializing argument 1 of âboost::_bi::list2<A1, A2>::list2(A1, A2) [with A1 = boost::_bi::value<ClientHandler>, A2 = boost::_bi::value<int>]â
    In file included from /usr/include/boost/bind.hpp:22,
                     from /usr/include/boost/thread/detail/thread.hpp:20,
                     from /usr/include/boost/thread/thread.hpp:22,
                     from share.h:4,
                     from server.cpp:2:
    /usr/include/boost/bind/bind.hpp: In constructor âboost::_bi::value<T>::value(const T&) [with T = ClientHandler]â:
    /usr/include/boost/bind/bind_mf2_cc.hpp:48:   instantiated from âboost::_bi::bind_t<Rt2, boost::_mfi::mf1<R, T, B1>, typename boost::_bi::list_av_2<A1, A2>::type> boost::bind(boost::type<R>, R (T::*)(B1), A1, A2) [with Rt2 = void, R = int, T = ClientHandler, B1 = int, A1 = ClientHandler, A2 = int]â
    /usr/include/boost/thread/detail/thread.hpp:243:   instantiated from âboost::thread::thread(F, A1, A2) [with F = int (ClientHandler::*)(int), A1 = ClientHandler, A2 = int]â
    server.cpp:101:   instantiated from here
    /usr/include/boost/bind/bind.hpp:116: error: no matching function for call to âClientHandler::ClientHandler(const ClientHandler&)â
    server.cpp:28: note: candidates are: ClientHandler::ClientHandler()
    server.cpp:23: note:                 ClientHandler::ClientHandler(ClientHandler&)
    In file included from /usr/include/boost/thread/thread.hpp:22,
                     from share.h:4,
                     from server.cpp:2:
    /usr/include/boost/thread/detail/thread.hpp: In constructor âboost::detail::thread_data<F>::thread_data(F&&) [with F = boost::_bi::bind_t<void, boost::_mfi::mf1<int, ClientHandler, int>, boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> > >]â:
    /usr/include/boost/thread/pthread/thread_heap_alloc.hpp:24:   instantiated from âT* boost::detail::heap_new(A1&&) [with T = boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf1<int, ClientHandler, int>, boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> > > >, A1 = boost::_bi::bind_t<void, boost::_mfi::mf1<int, ClientHandler, int>, boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> > >]â
    /usr/include/boost/thread/detail/thread.hpp:126:   instantiated from âstatic boost::detail::thread_data_ptr boost::thread::make_thread_info(F&&) [with F = boost::_bi::bind_t<void, boost::_mfi::mf1<int, ClientHandler, int>, boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> > >]â
    /usr/include/boost/thread/detail/thread.hpp:243:   instantiated from âboost::thread::thread(F, A1, A2) [with F = int (ClientHandler::*)(int), A1 = ClientHandler, A2 = int]â
    server.cpp:101:   instantiated from here
    /usr/include/boost/thread/detail/thread.hpp:44: error: no matching function for call to âboost::_bi::bind_t<void, boost::_mfi::mf1<int, ClientHandler, int>, boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> > >::bind_t(boost::_bi::bind_t<void, boost::_mfi::mf1<int, ClientHandler, int>, boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> > >)â
    /usr/include/boost/bind/bind.hpp:870: note: candidates are: boost::_bi::bind_t<R, F, L>::bind_t(F, const L&) [with R = void, F = boost::_mfi::mf1<int, ClientHandler, int>, L = boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> >]
    /usr/include/boost/bind/bind.hpp:865: note:                 boost::_bi::bind_t<void, boost::_mfi::mf1<int, ClientHandler, int>, boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> > >::bind_t(boost::_bi::bind_t<void, boost::_mfi::mf1<int, ClientHandler, int>, boost::_bi::list2<boost::_bi::value<ClientHandler>, boost::_bi::value<int> > >&)

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The first one is easy: there is no such thing in C++ as "vector". There is, however, "std::vector". If you read the man pages, you'll see where ExitThread and LPSOCKADDR are defined so you include the proper headers. It looks like you are also missing a copy constructor, but it's a little hard to tell.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    69
    Quote Originally Posted by tabstop View Post
    The first one is easy: there is no such thing in C++ as "vector". There is, however, "std::vector". If you read the man pages, you'll see where ExitThread and LPSOCKADDR are defined so you include the proper headers. It looks like you are also missing a copy constructor, but it's a little hard to tell.
    Ye I know "using namespace std;". I'm compiling it on linux, isnt ExitThread windows function? Does boost have their own function to exit thread or linux one?

  4. #4
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    Returning from a thread function implicitly exits the thread. Boost, being RAII-centric, doesn't seem to contain an explicit exit method.

  5. #5
    Registered User
    Join Date
    Mar 2011
    Posts
    69
    Quote Originally Posted by rags_to_riches View Post
    Returning from a thread function implicitly exits the thread. Boost, being RAII-centric, doesn't seem to contain an explicit exit method.
    Ok, the thing left to fix is boost thread and this :

    Code:
    struct sockaddr_in cinfo;
    int cilen = sizeof(cinfo);
    tmp.SetSock(accept(NHandler.ListenSocket, (struct sockaddr *) &cinfo, &cilen));
    Code:
    server.cpp:127: error: invalid conversion from âint*â to âsocklen_t*â
    server.cpp:127: error:   initializing argument 3 of âint accept(int, sockaddr*, socklen_t*)â

  6. #6
    Registered User
    Join Date
    Mar 2011
    Posts
    69
    Quote Originally Posted by kargo View Post
    Ok, the thing left to fix is boost thread and this :

    Code:
    struct sockaddr_in cinfo;
    int cilen = sizeof(cinfo);
    tmp.SetSock(accept(NHandler.ListenSocket, (struct sockaddr *) &cinfo, &cilen));
    Code:
    server.cpp:127: error: invalid conversion from âint*â to âsocklen_t*â
    server.cpp:127: error:   initializing argument 3 of âint accept(int, sockaddr*, socklen_t*)â
    Ok, I've done boost, but accept() isnt working yet. What I found is :

    The third argument of accept() was originally declared as an 'int *' (and is that under libc4 and libc5 and on many other systems like 4.x BSD, SunOS 4, SGI); a POSIX.1g draft standard wanted to change it into a 'size_t *', and that is what it is for SunOS 5. Later POSIX drafts have 'socklen_t *', and so do the Single Unix Specification and glibc2. Quoting Linus Torvalds:

    "_Any_ sane library _must_ have "socklen_t" be the same size as int. Anything else breaks any BSD socket layer stuff. POSIX initially did make it a size_t, and I (and hopefully others, but obviously not too many) complained to them very loudly indeed. Making it a size_t is completely broken, exactly because size_t very seldom is the same size as "int" on 64-bit architectures, for example. And it has to be the same size as "int" because that's what the BSD socket interface is. Anyway, the POSIX people eventually got a clue, and created "socklen_t". They shouldn't have touched it in the first place, but once they did they felt it had to have a named type for some unfathomable reason (probably somebody didn't like losing face over having done the original stupid thing, so they silently just renamed their blunder)."
    Do I miss some headers which has declaration of socklen_t? Or how to make it working?

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Apparently. Have you typed "man accept" into your terminal yet? Why not?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Writing a linux server in C
    By robsbots in forum Linux Programming
    Replies: 2
    Last Post: 11-14-2010, 09:37 AM
  2. problems with linux UDP server
    By Lopizda in forum Networking/Device Communication
    Replies: 5
    Last Post: 04-26-2007, 08:42 AM
  3. Linux Server
    By Carp in forum C++ Programming
    Replies: 3
    Last Post: 01-24-2003, 02:52 PM
  4. turbo linux 6.0 server
    By xds4lx in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 10-02-2002, 10:21 PM
  5. Linux X server installation
    By Unregistered in forum Linux Programming
    Replies: 3
    Last Post: 01-18-2002, 02:18 AM