View Single Post
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: UDP-Sockets chat application question

 
0
  #6
Nov 21st, 2008
> what is the relation between a socket and a port.
> I mean a socket is a special kind of file descriptor
> when i use file descriptors i don't use ports
> why we have to use ports when we use a socket?

a socket has no relation to a port.

a socket is created with the socket function has no name. this is no different from other file descriptors. a file descriptor also has no name. for example, stdin, stdout, stderr are file descriptors.
you use the open function to create a descriptor, the name that you give is the name of a file in the filesystem (which has an existence independant of file descriptors).

a remote process has no way to refer to a socket until a name (an address) is bound to it. an address is given to a socket via the bind function call. the address serves as a unique name using which a socket can be referred to.

In the UNIX domain, an address is simply a filesystem path. eg.
  1. sockaddr_un addr;
  2. ...
  3. std::strcpy( addr.sun_path, "/tmp/my_socket" ) ;
  4. addr.sun_family = AF_UNIX ;
  5. bind ( ... (sockaddr*) &addr, .... ) ;
The file name referred to is created as a socket in the system file name space. (write permission in the directory is required). these can be deleted with unlink().

in the Internet domain, the name is a tuple consisting of the IP address and a port number. a connection is a *unique* ordered tuple ( protocol, local ip address, local port, remote ip address, remote port). ports are an artifact of the addressing scheme to facilitate distinguishing between different connections on the same host (by composing unique tuples - at least the port is different - for each connection).

the same socket can be used to send and receive data at the same time. the following example would work, though we use the same socket:
  1. #include <sys/types.h>
  2. #include <sys/socket.h>
  3. #include <netinet/in.h>
  4. #include <arpa/inet.h>
  5. #include <netdb.h>
  6. #include <iostream>
  7. #include <cstring>
  8. #include <string>
  9.  
  10. enum { RECV_PORT = 5000, MSGSIZE = 1024 };
  11.  
  12. socklen_t addr_len = sizeof(sockaddr) ;
  13.  
  14. int listener( int socket_fd )
  15. {
  16. sockaddr_in my_addr ;
  17. std::memset( &my_addr, 0, sizeof(my_addr) ) ;
  18. my_addr.sin_family = AF_INET ;
  19. my_addr.sin_port = htons( RECV_PORT ) ;
  20. my_addr.sin_addr.s_addr = INADDR_ANY ;
  21.  
  22. if ( bind( socket_fd, (sockaddr*)&my_addr, addr_len ) != 0 )
  23. return 2 ;
  24.  
  25.  
  26. while( true )
  27. {
  28. char recv_data[MSGSIZE+1] ;
  29. sockaddr_in client_addr ;
  30.  
  31. int bytes_recd = recvfrom( socket_fd, recv_data, MSGSIZE, 0,
  32. (sockaddr*)&client_addr, &addr_len ) ;
  33. if( bytes_recd == -1 ) break ;
  34. recv_data[bytes_recd] = '\0' ;
  35.  
  36. std::cout << "from " << inet_ntoa(client_addr.sin_addr)
  37. << ':' << ntohs(client_addr.sin_port) << " - "
  38. << recv_data << std::endl ;
  39. }
  40. return 0 ;
  41. }
  42.  
  43. int sender( int socket_fd )
  44. {
  45. std::cout << "address of peer? " ;
  46. std::string address ; std::cin >> address >> std::ws ;
  47.  
  48. sockaddr_in peer_addr ;
  49. std::memset( &peer_addr, 0, sizeof(peer_addr) ) ;
  50. peer_addr.sin_family = AF_INET ;
  51. peer_addr.sin_port = htons( RECV_PORT ) ;
  52. peer_addr.sin_addr.s_addr =
  53. *(in_addr_t*)(gethostbyname( address.c_str() )->h_addr) ;
  54.  
  55. std::string send_str ;
  56. while( std::getline( std::cin, send_str ) )
  57. {
  58. send_str.resize(MSGSIZE) ;
  59. sendto( socket_fd, send_str.c_str(), MSGSIZE, 0,
  60. (sockaddr*)&peer_addr, addr_len ) ;
  61. }
  62. return 0 ;
  63. }
  64.  
  65. int main()
  66. {
  67. int socket_fd = socket( AF_INET, SOCK_DGRAM, 0 ) ;
  68. if( socket_fd == -1 ) return 1 ;
  69. return fork() == 0 ? listener( socket_fd ) : sender( socket_fd ) ;
  70. }

ps1: run with peer address "127.0.0.1" (localhost) for testing.
ps2: if you have follow-up questions that you want me to answer, do not post them in daniweb. i keep away from web sites that behave as if Internet Explorer is the only browser that i should use. (this post is from IE/Wine). you could use http://forums.devx.com/forumdisplay.php?s=&forumid=110
instead, which is the (only) other C++ student's forum that i look at on a somewhat regular basis.
Reply With Quote