LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 02-04-2011, 05:51 AM   #1
vbx_wx
Member
 
Registered: Feb 2010
Posts: 181

Rep: Reputation: 16
Sockets question


Hello. I guess its not posibile to create 2 sockets in the same project no ? I have an socket that is listening and the other one tries to connect and my connect() function does nothing,looks like waiting for something.How can i use threads to make them bot work in th same project ? Can someone help me with a scenario how to implement this? Where to create the thread,what does the thread function do. I use C++. Many thanks.
 
Old 02-04-2011, 06:02 AM   #2
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
It seems that you want someone to develop the entire project for you, whilst you sit back and enjoy the sunset.

What specific problems are you having with your project? And btw, it is possible to have more than one socket in use within an application. Employing threads (or multiple processes) is easiest, but not absolutely necessary.

Can you please post your code where you setup the "listen" socket, and the code where you setup the other socket that performs the connect().
 
Old 02-04-2011, 06:10 AM   #3
vbx_wx
Member
 
Registered: Feb 2010
Posts: 181

Original Poster
Rep: Reputation: 16
"It seems that you want someone to develop the entire project for you, whilst you sit back and enjoy the sunset." I must say this was funny.
I am developing a proxy server,so i need to listen to a connection and then I made when accept()-ing the connection to call connect to the server that the client connected to me said.(for example,cleint connects to me and says: "connect to google on port 80" and i must connect to google.

Code:
void Socket()
	{
		memset(&server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(9898);
		desc = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if(desc == -1)
		{
			cout << "Error in Socket()" << endl;
		}
	}
	void Bind()
	{
		if((::bind(desc, (sockaddr*)&server, sizeof(server))) == -1)
		{
			cout << "Error in Bind()" << endl;
		}
	}
	void Listen()
	{
		if((::listen(desc, 5)) == -1)
		{
			cout << "Error in Listen()" << endl;
		}
	}
	void Connect(string address, unsigned short port)
	{
		memset(&server2, 0, sizeof(server2));
		server2.sin_family = AF_INET;
		server2.sin_addr.s_addr = inet_addr(address.c_str());
		server2.sin_port = htons(port);

		desc2 = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if(desc2 == -1)
		{
			cout << "Error in Socket()" << endl;
		}

		if((::connect(desc2, (sockaddr*)&server2, sizeof(server2))) == SOCKET_ERROR)
		{
			cout << "Error in Connect()" << endl;
		}
		cout << "YOU ARE CONNECTED TO " << address << " ON PORT " << port << endl;
	}
	void Accept()
	{
#ifdef __linux__
		socklen_t intsock = sizeof(sock);
#endif
#ifdef WIN32
		int intsock = sizeof(sock);
#endif
		remoteSocket = ::accept(desc, (sockaddr*)&sock,  &intsock);
		if(remoteSocket == -1)
		{
			cout << "Error in Accept()" << endl;
			exit(1);
		}
		HandleConnection();
	}
After the HandleConnection is done(witch involves authetication between thoose too) I call connect to the server. I hope you get the ideea. Thanks.
 
Old 02-04-2011, 06:45 AM   #4
vbx_wx
Member
 
Registered: Feb 2010
Posts: 181

Original Poster
Rep: Reputation: 16
Do i need to create the thread in Accept() function so every client that connect receives its own thread ?
 
Old 02-04-2011, 06:51 AM   #5
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
One thing that I see is confusing is that the Socket() constructor creates a socket, and then Connect() does the same again (and yields a different socket descriptor).

From the high-level perspective, I would assume you have something like:
Code:
int main()
{
   Socket listenSock;

   listenSock.Bind();
   listenSock.Listen();

   listenSock.Accept();

   ...
}
I do not agree with your implementation of Accept(); this function should return a Socket object that represents the peer that has connected. For example:
Code:
void handlePeer(Socket& peerSock);

int main()
{
   Socket listenSock;

   listenSock.Bind();
   listenSock.Listen();

   while (true)
   {
      Socket* peerSock = listenSock.Accept();

      if (peerSock)
      {
         handlePeer(*peerSock);

         delete peerSock;
      }
   }
}

void handlePeer(Socket& peerSock)
{
   ...
}
P.S. Add a destructor to your Socket class that closes the socket descriptor.
 
Old 02-04-2011, 07:00 AM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Sorry, I read your reply with the code in haste; I was thinking that you had a class named Socket, but instead it seems that it is merely a function (perhaps part of a class?).

Anyhow, the common way to develop socket classes in an Object Oriented paradigm is to define a base-class for common socket operations into a Socket class, then specific operations applicable to the Server and Client into two other classes. I've done something similar to this:

Code:
                    Socket
                      ^
                      |
         +------------+-------------+
         |                          |
   TCPServerSocket --------->   TCPSocket
                    <friend>        ^
                                    |
                             TCPClientSocket
The Socket constructor should create a socket, aptly using socket(). It's destructor should close it.

Functions such as Bind(), Listen(), and Accept() should be defined in TCPServerSocket, but not in the TCPClientSocket (since these do not apply). The Connect() function should be defined in TCPClientSocket.

Functions such as Send() and Recv() should be defined in TCPSocket.

The Accept() function should return a TCPSocket. TCPSocket should have two constructors; a no-arg constructor and another that accepts a socket descriptor (this one is used by TCPServerSocket). Both constructors should be declared as protected.

P.S. Consider defining parameters for Bind(), such as port and address.

Last edited by dwhitney67; 02-04-2011 at 08:30 AM.
 
Old 02-04-2011, 07:44 AM   #7
vbx_wx
Member
 
Registered: Feb 2010
Posts: 181

Original Poster
Rep: Reputation: 16
Yes,ive done an implementation like this,but i lost my code,thats why now i made it simple,just a Server class.But how can i resolve my problem with 2 sockets created in the same program ?

edit: i will try to implement how you describe.i wil llet you know if i have problems.

Last edited by vbx_wx; 02-04-2011 at 07:50 AM.
 
Old 02-04-2011, 08:26 AM   #8
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Btw, I made an error earlier; TCPServerSocket should extend Socket, not TCPSocket. I'll attempt to update the diagram posted earlier.
 
Old 02-04-2011, 08:28 AM   #9
vbx_wx
Member
 
Registered: Feb 2010
Posts: 181

Original Poster
Rep: Reputation: 16
Something like this ?
Code:
class Socket {
protected:
	int desc;
public:
	Socket()
	{
		desc = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if(desc == -1)
		{
			cout << "Error in Socket()" << endl;
		}
	}
	Socket(int desc)
	{
		this->desc = desc;
	}
	~Socket()
	{
		#ifdef WIN32
		::closesocket(desc);
		#else
		::close(desc);
		#endif
	}

};

class TCPSocket: public Socket {
public:
	TCPSocket(): Socket() {}
	TCPSocket(int sockDesc): Socket(sockDesc) {}
	int Send(const char* buffer, int size)
	{
		int bytes_sent = 0;
		if((bytes_sent = ::send(desc, buffer, size, 0)) < 0)
		{
			cout << "Error in Send()" << endl;
		}
		return bytes_sent;
	}
	int Recv(char* buffer, int size) {
		int bytes_recv = 0;
		bytes_recv = ::recv(desc, buffer, size, 0);
		return bytes_recv;
	}
};

class ServerSocket: public TCPSocket {
private:
	sockaddr_in server;
public:
	ServerSocket(): TCPSocket()
	{
		memset(&server, 0, sizeof(server));
		server.sin_family = AF_INET;
		server.sin_addr.s_addr = INADDR_ANY;
		server.sin_port = htons(9898);
	}
	void Bind()
	{
		if((::bind(desc, (sockaddr*)&server, sizeof(server))) == SOCKET_ERROR)
		{
			cout << "Error in Bind()" << endl;
		}
	}
	void Listen()
	{
		if((::listen(desc, 5)) == SOCKET_ERROR)
		{
			cout << "Error in Listen()" << endl;
		}
	}
	Socket* Accept()
	{
		int remoteSocket = ::accept(desc, 0, 0);
		if(remoteSocket == SOCKET_ERROR)
		{
			cout << "Error in Accept()" << endl;
			exit(1);
		}
		return new TCPSocket(remoteSocket);
	}
};

class ClientSocket: public TCPSocket {
private:
	sockaddr_in client;
public:
	ClientSocket(): TCPSocket()
	{

	}
	void Connect(string address, unsigned short port)
	{
		memset(&client, 0, sizeof(client));
		client.sin_family = AF_INET;
		client.sin_addr.s_addr = inet_addr(address.c_str());
		client.sin_port = htons(port);


		if((::connect(desc, (sockaddr*)&client, sizeof(client))) == SOCKET_ERROR)
		{
			cout << "Error in Connect()" << endl;
		}
		cout << "YOU ARE CONNECTED TO " << address << " ON PORT " << port << endl;
	}
};


int main()
{
	ServerSocket s;
	s.Listen();
	while(true)
	{
		Socket* sock = s.Accept();
	}
	return 0;
}
edit: and then how is server gonna use send and recv functions ?

Last edited by vbx_wx; 02-04-2011 at 08:29 AM.
 
Old 02-04-2011, 08:41 AM   #10
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Quote:
Originally Posted by vbx_wx View Post
edit: and then how is server gonna use send and recv functions ?
You do not use the Server socket (aka Listen socket) to send/receive data. It is merely used to accept connections.

The descriptor returned by ::accept() is used to construct a TCPSocket, which in turn, is used to send/receive data to/from the peer (client). The allocated TCPSocket is what is "managed" by the server. Whether you want to create a separate thread or separate process to manage the connected client, is purely up to you.

Other than that, you seem to be on your away to a good design.

Last edited by dwhitney67; 02-04-2011 at 08:43 AM.
 
Old 02-04-2011, 08:49 AM   #11
vbx_wx
Member
 
Registered: Feb 2010
Posts: 181

Original Poster
Rep: Reputation: 16
OK,so accept should return a TCPSocket not a Socket how i did. An btw i am getting errors an all functions socket,bind,listen,accept

edit: strerror(errno) says No Error. Am i missing something ?
edit2: wait i forgot to initialize the part for windows with wsdata crap

Last edited by vbx_wx; 02-04-2011 at 08:58 AM.
 
Old 02-04-2011, 09:05 AM   #12
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,541

Rep: Reputation: 335Reputation: 335Reputation: 335Reputation: 335
Here's something I threw together real quick:
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>
#include <cassert>
#include <iostream>


class Socket
{
public:
   Socket()
   {
      m_desc = socket(AF_INET, SOCK_STREAM, 0);
      assert(m_desc != -1);
   }

   ~Socket()
   {
      close(m_desc);
   }

protected:
   Socket(int desc) : m_desc(desc) {}

   void fillAddress(const char* addr, const unsigned short port, sockaddr_in& sin)
   {
      memset(&sin, 0, sizeof(sin));

      if (!addr)
      {
         sin.sin_family      = AF_INET;
         sin.sin_addr.s_addr = htonl(INADDR_ANY);
         sin.sin_port        = htons(port);
      }
      else
      {
         // TODO
      }
   }

   int m_desc;
};

class TCPSocket : public Socket
{
public:
   int send(const char* buf, const size_t bufsize)
   {
      return ::send(m_desc, buf, bufsize, 0);
   }

   int recv(char* buf, const size_t bufSize)
   {
      return ::recv(m_desc, buf, bufSize, 0);
   }

protected:
   friend class TCPServerSocket;

   TCPSocket() {}

   TCPSocket(int desc) : Socket(desc) {}
};

class TCPServerSocket : public Socket
{
public:
   TCPServerSocket() {}

   void bind(const char* addr, const unsigned short port)
   {
      sockaddr_in sin;

      fillAddress(addr, port, sin);

      assert(::bind(m_desc, (sockaddr*) &sin, sizeof(sin)) == 0);
   }

   void listen(const int depth = 5)
   {
      assert(::listen(m_desc, depth) == 0);
   }

   TCPSocket* accept()
   {
      TCPSocket* peerSock = 0;
      int        desc = ::accept(m_desc, 0, 0);

      if (desc != -1)
      {
         peerSock = new TCPSocket(desc);
      }

      return peerSock;
   }
};

class TCPClientSocket : public TCPSocket
{
public:
   TCPClientSocket() {}

   void connect(const char* addr, const unsigned short port)
   {
      sockaddr_in sin;

      fillAddress(addr, port, sin);

      assert(::connect(m_desc, (sockaddr*) &sin, sizeof(sin)) == 0);
   }
};

class Server
{
public:
   Server(const char* addr, const unsigned short port)
   {
      m_listenSock.bind(addr, port);
      m_listenSock.listen();
   }

   void run()
   {
      while (true)
      {
         TCPSocket* peer = m_listenSock.accept();

         if (peer)
         {
            std::cout << "Peer connected!" << std::endl;
            handlePeer(peer);
            delete peer;
         }
      }
   }

private:
   void handlePeer(TCPSocket* peer)
   {
      char recv[1024];
      bool connected = true;

      while (connected)
      {
         int len = peer->recv(recv, sizeof(recv) - 1);

         if (len > 0)
         {
            recv[len] = '\0';
            std::cout << "Received from peer: " << recv << std::endl;
         }
         else if (len == 0)
         {
            std::cout << "Peer disconnected!" << std::endl;
            connected = false;
         }
      }
   }

   TCPServerSocket m_listenSock;
};

class Client
{
public:
   Client(const char* addr, const unsigned short port)
   {
      m_socket.connect(addr, port);
   }

   void run()
   {
      static const char* hello = "Hello Server!";

      m_socket.send(hello, strlen(hello));
   }

private:
   TCPClientSocket m_socket;
};

int main()
{
   int pid = fork();

   if (pid < 0)
   {
      perror("fork() failed");
      return -1;
   }

   if (pid > 0)
   {
      Server server(0, 12345);   // INADDR_ANY and port 12345
      server.run();
   }
   else
   {
      sleep(1);   // allow time for the server to set up.

      Client client(0, 12345);   // establish connection to INADDR_ANY at port 12345
      client.run();
   }
}
P.S. Normally I would separate the client and server into two distinct applications, rather than do the fork() as shown in the example above.

Last edited by dwhitney67; 02-04-2011 at 09:10 AM.
 
Old 02-04-2011, 09:21 AM   #13
vbx_wx
Member
 
Registered: Feb 2010
Posts: 181

Original Poster
Rep: Reputation: 16
Thanks ,that looks good
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
A question about netlink sockets alfrag Linux - Newbie 1 12-26-2008 08:48 AM
Simple sockets program question default5 Programming 10 06-11-2008 08:15 AM
C sockets question borgy_t Programming 6 03-12-2005 10:28 PM
Question about Sockets Programming sibtay Programming 2 09-24-2004 05:04 PM
sockets question sibtay Programming 2 08-23-2004 12:51 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 10:46 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration