SlideShare a Scribd company logo
Components of computer systems often have dependencies
--
other components that must be
installed before they will function properly. These dependencies are frequently shared by
multiple components. For example, both the TELNET client program and the FTP cli
ent
program require that the TCP/IP networking software be installed before they can operate. If you
install TCP/IP and the TELNET client program, and later decide to add the FTP client program,
you do not need to reinstall TCP/IP.
For some components it
would not be a problem if the components on which they depended were
reinstalled; it would just waste some resources. But for others, like TCP/IP, some component
configuration may be destroyed if the component was reinstalled.
It is useful to be able to r
emove components that are no longer needed. When this is done,
components that only support the removed component may also be removed, freeing up disk
space, memory, and other resources. But a supporting component, not explicitly installed, may
be removed
only if all components which depend on it are also removed. For example, removing
the FTP client program and TCP/IP would mean the TELNET client program, which was not
removed, would no longer operate. Likewise, removing TCP/IP by itself would cause the fa
ilure
of both the TELNET and the FTP client programs. Also if we installed TCP/IP to support our
own development, then installed the TELNET client (which depends on TCP/IP) and then still
later removed the TELNET client, we would not want TCP/IP to be remo
ved.
We want a program to automate the process of adding and removing components. To do this we
will maintain a record of installed components and component dependencies. A component can
be installed explicitly in response to a command (unless it is alrea
dy installed), or implicitly if it
is needed for some other component being installed. Likewise, a component, not explicitly
installed, can be explicitly removed in response to a command (if it is not needed to support
other components) or implicitly remov
ed if it is no longer needed to support another component.
Input
The input will contain a sequence of commands (as described below), each on a separate line
containing no more than eighty characters. Item names are case sensitive, and each is no longer
th
an ten characters. The command names (
DEPEND
,
INSTALL
,
REMOVE
and
LIST
) always
appear in uppercase starting in column one, and item names are separated from the command
name and each other by one or more spaces. All appropriate
DEPEND
commands will appear
before the occurrence of any
INSTALL
dependencies. The end of the input is marked by a line
containing only the word
END
.
Command Syntax
Interpretation/Response
DEPEND item1 item2 [item3 ...]
item1
depends on
item2
(and
item3
...)
INSTALL item1
install
item1
and those on which it depends
REMOVE item1
remove
item1
, and those on whch it depends, if possible
LIST
list the names of all currently
-
installed components
Output
Echo each line of input. Follow each echoed
INSTALL
or
REMOVE
line with the actions taken
in response, making certain that the actions are given in the proper order. Also identify
exceptional conditions (see
Expected Output
, below, for examples of all case
s). For the
LIST
command, display the names of the currently installed components. No output, except the echo,
is produced for a
DEPEND
command or the line containing
END
. There will be at most one
dependency list per item.
Sample Input
DEPEND TELNET TC
PIP NETCARD
DEPEND TCPIP NETCARD
DEPEND DNS TCPIP NETCARD
DEPEND BROWSER TCPIP HTML
INSTALL NETCARD
INSTALL TELNET
INSTALL foo
REMOVE NETCARD
INSTALL BROWSER
INSTALL DNS
LIST
REMOVE TELNET
REMOVE NETCARD
REMOVE DNS
REMOVE NETCARD
INSTALL NETCARD
REMOVE
TCPIP
REMOVE BROWSER
REMOVE TCPIP
LIST
END
Output for the Sample Output
DEPEND TELNET TCPIP NETCARD
DEPEND TCPIP NETCARD
DEPEND DNS TCPIP NETCARD
DEPEND BROWSER TCPIP HTML
INSTALL NETCARD
Installing NETCARD
INSTALL TELNET
Installing TCPIP
Installing TELNET
INSTALL foo
Installing foo
REMOVE NETCARD
NETCARD is still needed.
INSTALL BROWSER
Installing HTML
Installing BROWSER
INSTALL DNS
Installing DNS
LIST
HTML
BROWSER
DNS
NETCARD
foo
TCPIP
TELNET
REMOVE
TELNET
Removing TELNET
REMOVE NETCARD
NETCARD is still needed.
REMOVE DNS
Removing DNS
REMOVE NETCARD
NETCARD is still needed.
INSTALL NETCARD
NETCARD is already installed.
REMOVE TCPIP
TCPIP is still needed.
REMOVE BROWSER
Removing BROWSER
Removing HTML
Removing TCPIP
REMOVE TCPIP
TCPIP is not installed.
LIST
NETCARD
foo
END
Solution
TCPStream Class
Interface
The TCPStream class provides methods to send and receive data over a TCP/IP connection. It
contains a connected socket descriptor and information about the peer – either client or server –
in the form of the IP address and TCP port. TCPStream includes simple get methods that return
address and port, but not the socket descriptor which is kept private. One of the advantages of
programming with objects is the ability to logically group data members and methods to avoid
exposing data, in this case the socket descriptor, to the calling program that it does not need to
see. Each connection is completely encapsulated in each TCPStream object.
TCPStream objects are created by TCPConnector and TCPAcceptor objects only, so the
TCPStream constructors must be declared private to prevent them from being called directly by
any other objects. The TCPStream class grants friend privileges to the TCPConnector and
TCPAcceptor classes so they can access the TCPStream constructors to supply connected socket
descriptors.
#include
#include
#include
#include
using namespace std
class TCPStream
{
int m_sd;
string m_peerIP;
int m_peerPort;
public:
friend class TCPAcceptor;
friend class TCPConnector;
~TCPStream();
ssize_t send(char* buffer, size_t len);
ssize_t receive(char* buffer, size_t len);
string getPeerIP();
int getPeerPort();
private:
TCPStream(int sd, struct sockaddr_in* address);
TCPStream();
TCPStream(const TCPStream& stream);
};
Constructor
The constructor stores the connected socket descriptor then converts the socket information
structure fields to a peer IP address string and peer TCP port. These parameters can be inspected
with calls to TCPStream::getPeerIP() and TCPStream::getPeerPort().
#include
#include "tcpstream.h"
TCPStream::TCPStream(int sd, struct sockaddr_in* address) : msd(sd) {
char ip[50];
inet_ntop(PF_INET, (struct in_addr*)&(address->sin_addr.s_addr),
ip, sizeof(ip)-1);
m_peerIP = ip;
m_peerPort = ntohs(address->sin_port);
}
Destructor
The destructor simply closes the connection.
TCPStream::~TCPStream()
{
close(m_sd);
}
Network I/O Methods
TCPStream::send() and TCPStream::receive() simply wrap calls to read() and write(), returning
the number of bytes sent and bytes received, respectively. No additional buffering or other
capabilities are added.
Get Peer Information
TCPStream::getPeerIP() and TCPStream::getPeerPort() return the IP address and TCP port
information of the peer to which the network application, client or server, are connected. You
can get the same information from the sockets getpeername() function but it far easier to just
capture that information when the connections are established. Clients know in advance to where
they are connecting and the client’s socket address is returned the accept() function when the
server accepts a client connection – see the TCPAcceptor::accept() method definition. In both
cases the socket address information is passed to the TCPStream object when it is constructed.
TCPConnector Class
Interface
TCPConnector provides the connect() method to actively establish a connection with a server. It
accepts the server port and a string containing the server host name or IP address. If successful, a
pointer to a TCPStream object is returned to the caller.
#include
#include "tcpstream.h"
class TCPConnector
{
public:
TCPStream* connect(int port, const char* server);
private:
int resolveHost(const char* host, struct in_addr* addr);
};
Constructor/Destructor
The TCPConnector class does not use any member variables so the default constructor and
destructor generated by the C++ compiler are fine. No others are defined.
Connect to Server
[Lines 6-12] TCPConnector::connect() call takes a server host name or IP address string and the
server listening port as arguments. The server struct sockaddr_in sin_family is set to PF_INET
and the sin_port is set to the TCP port on which the server is listening for connections.
#include
#include
#include
#include "tcpconnector.h"
TCPStream* TCPConnector::connect(const char* server, int port)
{
struct sockaddr_in address;
memset (&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(port);
if (resolveHostName(server, &(address.sin_addr)) != 0) {
inet_pton(PF_INET, server, &(address.sin_addr));
}
int sd = socket(AF_INET, SOCK_STREAM, 0);
if (::connect(sd, (struct sockaddr*)&address, sizeof(address)) != 0) {
return NULL;
}
return new TCPStream(sd, &address);
}
int TCPConnector::resolveHostName(const char* hostname, struct in_addr* addr)
{
struct addrinfo *res;
int result = getaddrinfo (hostname, NULL, NULL, &res);
if (result == 0) {
memcpy(addr, &((struct sockaddr_in *) res->ai_addr)->sin_addr,
sizeof(struct in_addr));
freeaddrinfo(res);
}
return result;
}
TCPAcceptor Class
Interface
TCPAcceptor includes member variables for the listening socket descriptor, the socket address
information – IP address and TCP port – and a flag that indicates whether or not the
TCPAcceptor has started listening for connections.
Two public methods are supported. One to start the listening and the other to accept connections.
#include
#include
#include "tcpstream.h"
using namespace std;
class TCPAcceptor
{
int m_lsd;
string m_address;
int m_port;
bool m_listening;
public:
TCPAcceptor(int port, const char* address="");
~TCPAcceptor();
int start();
TCPStream* accept();
private:
TCPAcceptor() {}
};
Constructor
The constructor sets the member variables to as shown here. Setting m_lsd indicates that the
lisetning socket has not been created.
#include
#include
#include
#include "tcpacceptor.h"
TCPAcceptor::TCPAcceptor(int port, const char* address)
: m_lsd(0), m_port(port), m_address(address), m_listening(false) {}
Destructor
If the listening socket has been created then it is closed in the destructor.
TCPAcceptor::~TCPAcceptor()
{
if (m_lsd > 0) {
close(m_lsd);
}
}
Start Listening for Connections
[Line 3-5] Creating a listening socket involves the most socket calls of any operation. Before
going through the series of calls, TCPAcceptor::start() checks to see if a listening socket already
exists. If so, the method just returns 0.
int TCPAcceptor::start()
{
if (m_listening == true) {
return 0;
}
m_lsd = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in address;
memset(&address, 0, sizeof(address));
address.sin_family = PF_INET;
address.sin_port = htons(m_port);
if (m_address.size() > 0) {
inet_pton(PF_INET, m_address.c_str(), &(address.sin_addr));
}
else {
address.sin_addr.s_addr = INADDR_ANY;
}
int optval = 1;
setsockopt(m_lsd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval);
int result = bind(m_lsd, (struct sockaddr*)&address, sizeof(address));
if (result != 0) {
perror("bind() failed");
return result;
}
result = listen(m_lsd, 5);
if (result != 0) {
perror("listen() failed");
return result;
}
m_listening = true;
return result;
}
TCPStream* TCPAcceptor::accept()
{
if (m_listening == false) {
return NULL;
}
struct sockaddr_in address;
socklen_t len = sizeof(address);
memset(&address, 0, sizeof(address));
int sd = ::accept(m_lsd, (struct sockaddr*)&address, &len);
if (sd < 0) {
perror("accept() failed");
return NULL;
}
return new TCPStream(sd, &address);
}
#include
#include
#include "tcpacceptor.h"
int main(int argc, char** argv)
{
if (argc < 2 || argc > 4) {
printf("usage: server [] ");
exit(1);
}
TCPStream* stream = NULL;
TCPAcceptor* acceptor = NULL;
if (argc == 3) {
acceptor = new TCPAcceptor(atoi(argv[1]), argv[2]);
}
else {
acceptor = new TCPAcceptor(atoi(argv[1]));
}
if (acceptor->start() == 0) {
while (1) {
stream = acceptor->accept();
if (stream != NULL) {
size_t len;
char line[256];
while ((len = stream->receive(line, sizeof(line))) > 0) {
line[len] = NULL;
printf("received - %s ", line);
stream->send(line, len);
}
delete stream;
}
}
}
perror("Could not start the server");
exit(-1);
}
Echo Client
The client application takes the server TCP port and IP address on the command line. For each
connection a string is displayed and sent to the server, the echoed string is received back and
displayed, then the connection is closed. The client will be defined in the file client.cpp
#include
#include
#include
#include "tcpconnector.h"
using namespace std;
int main(int argc, char** argv)
{
if (argc != 3) {
printf("usage: %s  ", argv[0]);
exit(1);
}
int len;
string message;
char line[256];
TCPConnector* connector = new TCPConnector();
TCPStream* stream = connector->connect(argv[2], atoi(argv[1]));
if (stream) {
message = "Is there life on Mars?";
stream->send(message.c_str(), message.size());
printf("sent - %s ", message.c_str());
len = stream->receive(line, sizeof(line));
line[len] = NULL;
printf("received - %s ", line);
delete stream;
}
stream = connector->connect(argv[2], atoi(argv[1]));
if (stream) {
message = "Why is there air?";
stream->send(message.c_str(), message.size());
printf("sent - %s ", message.c_str());
len = stream->receive(line, sizeof(line));
line[len] = NULL;
printf("received - %s ", line);
delete stream;
}
exit(0);
}
#include
#include
#include
#include
using namespace std
class TCPStream
{
int m_sd;
string m_peerIP;
int m_peerPort;
public:
friend class TCPAcceptor;
friend class TCPConnector;
~TCPStream();
ssize_t send(char* buffer, size_t len);
ssize_t receive(char* buffer, size_t len);
string getPeerIP();
int getPeerPort();
private:
TCPStream(int sd, struct sockaddr_in* address);
TCPStream();
TCPStream(const TCPStream& stream);
};

More Related Content

DOCX
PDF
nwlab-ex1.pdf
PDF
Socket programming
PPT
Networking & Socket Programming In Java
PPT
Socket System Calls
PPT
Application Layer and Socket Programming
PPT
Unit 8 Java
nwlab-ex1.pdf
Socket programming
Networking & Socket Programming In Java
Socket System Calls
Application Layer and Socket Programming
Unit 8 Java

Similar to Components of computer systems often have dependencies--other co.pdf (20)

DOCX
Student Name _________________________________ Date _____________SE.docx
PPTX
Lecture 1 Socket programming elementary tcp sockets.pptx
DOC
Arp Dan Ipconfig Syntax
PPT
Md13 networking
PPT
FMS Administration Seminar
PPT
Network Programming in Java
PDF
CC++ echo serverThis assignment is designed to introduce network .pdf
PPT
Network programming in Java
DOCX
1 SEC450 ACL Tutorial This document highlights.docx
PPT
Np unit2
PPT
Basic socket programming
PPTX
QoS Classification on Cisco IOS Router
PDF
Ip Access Lists
PDF
CSS L17 - DOS COMMANDS IN COMPUTER NETWORKING
PPT
TCP WRAPPERS and XINETD
PPT
Lession2 Xinetd
PDF
Network configuration in Linux
DOCX
Rpc mechanism
PDF
Arduino LED maXbox starter18_3
PPTX
Linux Systems Prograramming: Unix Domain, Internet Domain (TCP, UDP) Socket P...
Student Name _________________________________ Date _____________SE.docx
Lecture 1 Socket programming elementary tcp sockets.pptx
Arp Dan Ipconfig Syntax
Md13 networking
FMS Administration Seminar
Network Programming in Java
CC++ echo serverThis assignment is designed to introduce network .pdf
Network programming in Java
1 SEC450 ACL Tutorial This document highlights.docx
Np unit2
Basic socket programming
QoS Classification on Cisco IOS Router
Ip Access Lists
CSS L17 - DOS COMMANDS IN COMPUTER NETWORKING
TCP WRAPPERS and XINETD
Lession2 Xinetd
Network configuration in Linux
Rpc mechanism
Arduino LED maXbox starter18_3
Linux Systems Prograramming: Unix Domain, Internet Domain (TCP, UDP) Socket P...
Ad

More from alamodeindia1 (14)

PDF
Compute SS, variance, standard deviation, and range for the followin.pdf
PDF
Connect compensation components to organizational strategy.Solut.pdf
PDF
Compute the Mean and the Standard deviation. Class 1, 0 up to 5 Fre.pdf
PDF
compute the present value of a perpetuity bond that pays a monthly c.pdf
PDF
Consider a large lot of electronic components where there is interes.pdf
PDF
Compute the rate of return for the investment represented by the fol.pdf
PDF
Consider a discrete random variable, X, having pmf pX(x) = (1 )^.pdf
PDF
Consider a 6 x 4 matrix. Prove that every column in A is in the span.pdf
PDF
Consider a family tree that consists of just you, your parents,their.pdf
PDF
Consider a discrete random variable X with moment generating functio.pdf
PDF
Consider a dinner table where n dining philosophers are seated. Each.pdf
PDF
Consider a $6500 piece of machinery , with a 5 year depreciable like.pdf
PDF
Conduct a company review of Starbucks. What are their unique growth .pdf
PDF
Computer-Based Training (CBT) Methods Please respond to the foll.pdf
Compute SS, variance, standard deviation, and range for the followin.pdf
Connect compensation components to organizational strategy.Solut.pdf
Compute the Mean and the Standard deviation. Class 1, 0 up to 5 Fre.pdf
compute the present value of a perpetuity bond that pays a monthly c.pdf
Consider a large lot of electronic components where there is interes.pdf
Compute the rate of return for the investment represented by the fol.pdf
Consider a discrete random variable, X, having pmf pX(x) = (1 )^.pdf
Consider a 6 x 4 matrix. Prove that every column in A is in the span.pdf
Consider a family tree that consists of just you, your parents,their.pdf
Consider a discrete random variable X with moment generating functio.pdf
Consider a dinner table where n dining philosophers are seated. Each.pdf
Consider a $6500 piece of machinery , with a 5 year depreciable like.pdf
Conduct a company review of Starbucks. What are their unique growth .pdf
Computer-Based Training (CBT) Methods Please respond to the foll.pdf
Ad

Recently uploaded (20)

PDF
International_Financial_Reporting_Standa.pdf
PDF
Paper A Mock Exam 9_ Attempt review.pdf.
PDF
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
PDF
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 1)
PDF
Empowerment Technology for Senior High School Guide
PPTX
Unit 4 Computer Architecture Multicore Processor.pptx
PDF
Environmental Education MCQ BD2EE - Share Source.pdf
PDF
FORM 1 BIOLOGY MIND MAPS and their schemes
PDF
Weekly quiz Compilation Jan -July 25.pdf
PPTX
TNA_Presentation-1-Final(SAVE)) (1).pptx
PPTX
ELIAS-SEZIURE AND EPilepsy semmioan session.pptx
PDF
MBA _Common_ 2nd year Syllabus _2021-22_.pdf
PDF
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 2).pdf
PDF
CISA (Certified Information Systems Auditor) Domain-Wise Summary.pdf
PDF
1.3 FINAL REVISED K-10 PE and Health CG 2023 Grades 4-10 (1).pdf
PDF
Chinmaya Tiranga quiz Grand Finale.pdf
PDF
Practical Manual AGRO-233 Principles and Practices of Natural Farming
PDF
احياء السادس العلمي - الفصل الثالث (التكاثر) منهج متميزين/كلية بغداد/موهوبين
PPTX
20th Century Theater, Methods, History.pptx
PPTX
A powerpoint presentation on the Revised K-10 Science Shaping Paper
International_Financial_Reporting_Standa.pdf
Paper A Mock Exam 9_ Attempt review.pdf.
FOISHS ANNUAL IMPLEMENTATION PLAN 2025.pdf
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 1)
Empowerment Technology for Senior High School Guide
Unit 4 Computer Architecture Multicore Processor.pptx
Environmental Education MCQ BD2EE - Share Source.pdf
FORM 1 BIOLOGY MIND MAPS and their schemes
Weekly quiz Compilation Jan -July 25.pdf
TNA_Presentation-1-Final(SAVE)) (1).pptx
ELIAS-SEZIURE AND EPilepsy semmioan session.pptx
MBA _Common_ 2nd year Syllabus _2021-22_.pdf
BP 704 T. NOVEL DRUG DELIVERY SYSTEMS (UNIT 2).pdf
CISA (Certified Information Systems Auditor) Domain-Wise Summary.pdf
1.3 FINAL REVISED K-10 PE and Health CG 2023 Grades 4-10 (1).pdf
Chinmaya Tiranga quiz Grand Finale.pdf
Practical Manual AGRO-233 Principles and Practices of Natural Farming
احياء السادس العلمي - الفصل الثالث (التكاثر) منهج متميزين/كلية بغداد/موهوبين
20th Century Theater, Methods, History.pptx
A powerpoint presentation on the Revised K-10 Science Shaping Paper

Components of computer systems often have dependencies--other co.pdf

  • 1. Components of computer systems often have dependencies -- other components that must be installed before they will function properly. These dependencies are frequently shared by multiple components. For example, both the TELNET client program and the FTP cli ent program require that the TCP/IP networking software be installed before they can operate. If you install TCP/IP and the TELNET client program, and later decide to add the FTP client program, you do not need to reinstall TCP/IP. For some components it would not be a problem if the components on which they depended were reinstalled; it would just waste some resources. But for others, like TCP/IP, some component configuration may be destroyed if the component was reinstalled. It is useful to be able to r emove components that are no longer needed. When this is done, components that only support the removed component may also be removed, freeing up disk space, memory, and other resources. But a supporting component, not explicitly installed, may be removed only if all components which depend on it are also removed. For example, removing the FTP client program and TCP/IP would mean the TELNET client program, which was not removed, would no longer operate. Likewise, removing TCP/IP by itself would cause the fa ilure of both the TELNET and the FTP client programs. Also if we installed TCP/IP to support our own development, then installed the TELNET client (which depends on TCP/IP) and then still later removed the TELNET client, we would not want TCP/IP to be remo ved. We want a program to automate the process of adding and removing components. To do this we will maintain a record of installed components and component dependencies. A component can be installed explicitly in response to a command (unless it is alrea dy installed), or implicitly if it is needed for some other component being installed. Likewise, a component, not explicitly installed, can be explicitly removed in response to a command (if it is not needed to support other components) or implicitly remov ed if it is no longer needed to support another component. Input
  • 2. The input will contain a sequence of commands (as described below), each on a separate line containing no more than eighty characters. Item names are case sensitive, and each is no longer th an ten characters. The command names ( DEPEND , INSTALL , REMOVE and LIST ) always appear in uppercase starting in column one, and item names are separated from the command name and each other by one or more spaces. All appropriate DEPEND commands will appear before the occurrence of any INSTALL dependencies. The end of the input is marked by a line containing only the word END . Command Syntax Interpretation/Response DEPEND item1 item2 [item3 ...] item1 depends on item2 (and item3 ...) INSTALL item1 install item1 and those on which it depends REMOVE item1
  • 3. remove item1 , and those on whch it depends, if possible LIST list the names of all currently - installed components Output Echo each line of input. Follow each echoed INSTALL or REMOVE line with the actions taken in response, making certain that the actions are given in the proper order. Also identify exceptional conditions (see Expected Output , below, for examples of all case s). For the LIST command, display the names of the currently installed components. No output, except the echo, is produced for a DEPEND command or the line containing END . There will be at most one dependency list per item. Sample Input DEPEND TELNET TC PIP NETCARD DEPEND TCPIP NETCARD DEPEND DNS TCPIP NETCARD DEPEND BROWSER TCPIP HTML INSTALL NETCARD INSTALL TELNET INSTALL foo REMOVE NETCARD
  • 4. INSTALL BROWSER INSTALL DNS LIST REMOVE TELNET REMOVE NETCARD REMOVE DNS REMOVE NETCARD INSTALL NETCARD REMOVE TCPIP REMOVE BROWSER REMOVE TCPIP LIST END Output for the Sample Output DEPEND TELNET TCPIP NETCARD DEPEND TCPIP NETCARD DEPEND DNS TCPIP NETCARD DEPEND BROWSER TCPIP HTML INSTALL NETCARD Installing NETCARD INSTALL TELNET Installing TCPIP Installing TELNET INSTALL foo Installing foo REMOVE NETCARD NETCARD is still needed. INSTALL BROWSER Installing HTML Installing BROWSER INSTALL DNS Installing DNS LIST HTML BROWSER
  • 5. DNS NETCARD foo TCPIP TELNET REMOVE TELNET Removing TELNET REMOVE NETCARD NETCARD is still needed. REMOVE DNS Removing DNS REMOVE NETCARD NETCARD is still needed. INSTALL NETCARD NETCARD is already installed. REMOVE TCPIP TCPIP is still needed. REMOVE BROWSER Removing BROWSER Removing HTML Removing TCPIP REMOVE TCPIP TCPIP is not installed. LIST NETCARD foo END Solution TCPStream Class Interface The TCPStream class provides methods to send and receive data over a TCP/IP connection. It contains a connected socket descriptor and information about the peer – either client or server – in the form of the IP address and TCP port. TCPStream includes simple get methods that return
  • 6. address and port, but not the socket descriptor which is kept private. One of the advantages of programming with objects is the ability to logically group data members and methods to avoid exposing data, in this case the socket descriptor, to the calling program that it does not need to see. Each connection is completely encapsulated in each TCPStream object. TCPStream objects are created by TCPConnector and TCPAcceptor objects only, so the TCPStream constructors must be declared private to prevent them from being called directly by any other objects. The TCPStream class grants friend privileges to the TCPConnector and TCPAcceptor classes so they can access the TCPStream constructors to supply connected socket descriptors. #include #include #include #include using namespace std class TCPStream { int m_sd; string m_peerIP; int m_peerPort; public: friend class TCPAcceptor; friend class TCPConnector; ~TCPStream(); ssize_t send(char* buffer, size_t len); ssize_t receive(char* buffer, size_t len); string getPeerIP(); int getPeerPort(); private: TCPStream(int sd, struct sockaddr_in* address); TCPStream(); TCPStream(const TCPStream& stream); }; Constructor The constructor stores the connected socket descriptor then converts the socket information structure fields to a peer IP address string and peer TCP port. These parameters can be inspected with calls to TCPStream::getPeerIP() and TCPStream::getPeerPort().
  • 7. #include #include "tcpstream.h" TCPStream::TCPStream(int sd, struct sockaddr_in* address) : msd(sd) { char ip[50]; inet_ntop(PF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, sizeof(ip)-1); m_peerIP = ip; m_peerPort = ntohs(address->sin_port); } Destructor The destructor simply closes the connection. TCPStream::~TCPStream() { close(m_sd); } Network I/O Methods TCPStream::send() and TCPStream::receive() simply wrap calls to read() and write(), returning the number of bytes sent and bytes received, respectively. No additional buffering or other capabilities are added. Get Peer Information TCPStream::getPeerIP() and TCPStream::getPeerPort() return the IP address and TCP port information of the peer to which the network application, client or server, are connected. You can get the same information from the sockets getpeername() function but it far easier to just capture that information when the connections are established. Clients know in advance to where they are connecting and the client’s socket address is returned the accept() function when the server accepts a client connection – see the TCPAcceptor::accept() method definition. In both cases the socket address information is passed to the TCPStream object when it is constructed. TCPConnector Class Interface TCPConnector provides the connect() method to actively establish a connection with a server. It accepts the server port and a string containing the server host name or IP address. If successful, a pointer to a TCPStream object is returned to the caller. #include #include "tcpstream.h" class TCPConnector {
  • 8. public: TCPStream* connect(int port, const char* server); private: int resolveHost(const char* host, struct in_addr* addr); }; Constructor/Destructor The TCPConnector class does not use any member variables so the default constructor and destructor generated by the C++ compiler are fine. No others are defined. Connect to Server [Lines 6-12] TCPConnector::connect() call takes a server host name or IP address string and the server listening port as arguments. The server struct sockaddr_in sin_family is set to PF_INET and the sin_port is set to the TCP port on which the server is listening for connections. #include #include #include #include "tcpconnector.h" TCPStream* TCPConnector::connect(const char* server, int port) { struct sockaddr_in address; memset (&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_port = htons(port); if (resolveHostName(server, &(address.sin_addr)) != 0) { inet_pton(PF_INET, server, &(address.sin_addr)); } int sd = socket(AF_INET, SOCK_STREAM, 0); if (::connect(sd, (struct sockaddr*)&address, sizeof(address)) != 0) { return NULL; } return new TCPStream(sd, &address); } int TCPConnector::resolveHostName(const char* hostname, struct in_addr* addr) { struct addrinfo *res; int result = getaddrinfo (hostname, NULL, NULL, &res); if (result == 0) {
  • 9. memcpy(addr, &((struct sockaddr_in *) res->ai_addr)->sin_addr, sizeof(struct in_addr)); freeaddrinfo(res); } return result; } TCPAcceptor Class Interface TCPAcceptor includes member variables for the listening socket descriptor, the socket address information – IP address and TCP port – and a flag that indicates whether or not the TCPAcceptor has started listening for connections. Two public methods are supported. One to start the listening and the other to accept connections. #include #include #include "tcpstream.h" using namespace std; class TCPAcceptor { int m_lsd; string m_address; int m_port; bool m_listening; public: TCPAcceptor(int port, const char* address=""); ~TCPAcceptor(); int start(); TCPStream* accept(); private: TCPAcceptor() {} }; Constructor The constructor sets the member variables to as shown here. Setting m_lsd indicates that the lisetning socket has not been created. #include #include #include
  • 10. #include "tcpacceptor.h" TCPAcceptor::TCPAcceptor(int port, const char* address) : m_lsd(0), m_port(port), m_address(address), m_listening(false) {} Destructor If the listening socket has been created then it is closed in the destructor. TCPAcceptor::~TCPAcceptor() { if (m_lsd > 0) { close(m_lsd); } } Start Listening for Connections [Line 3-5] Creating a listening socket involves the most socket calls of any operation. Before going through the series of calls, TCPAcceptor::start() checks to see if a listening socket already exists. If so, the method just returns 0. int TCPAcceptor::start() { if (m_listening == true) { return 0; } m_lsd = socket(PF_INET, SOCK_STREAM, 0); struct sockaddr_in address; memset(&address, 0, sizeof(address)); address.sin_family = PF_INET; address.sin_port = htons(m_port); if (m_address.size() > 0) { inet_pton(PF_INET, m_address.c_str(), &(address.sin_addr)); } else { address.sin_addr.s_addr = INADDR_ANY; } int optval = 1; setsockopt(m_lsd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval); int result = bind(m_lsd, (struct sockaddr*)&address, sizeof(address)); if (result != 0) { perror("bind() failed");
  • 11. return result; } result = listen(m_lsd, 5); if (result != 0) { perror("listen() failed"); return result; } m_listening = true; return result; } TCPStream* TCPAcceptor::accept() { if (m_listening == false) { return NULL; } struct sockaddr_in address; socklen_t len = sizeof(address); memset(&address, 0, sizeof(address)); int sd = ::accept(m_lsd, (struct sockaddr*)&address, &len); if (sd < 0) { perror("accept() failed"); return NULL; } return new TCPStream(sd, &address); } #include #include #include "tcpacceptor.h" int main(int argc, char** argv) { if (argc < 2 || argc > 4) { printf("usage: server [] "); exit(1); } TCPStream* stream = NULL; TCPAcceptor* acceptor = NULL;
  • 12. if (argc == 3) { acceptor = new TCPAcceptor(atoi(argv[1]), argv[2]); } else { acceptor = new TCPAcceptor(atoi(argv[1])); } if (acceptor->start() == 0) { while (1) { stream = acceptor->accept(); if (stream != NULL) { size_t len; char line[256]; while ((len = stream->receive(line, sizeof(line))) > 0) { line[len] = NULL; printf("received - %s ", line); stream->send(line, len); } delete stream; } } } perror("Could not start the server"); exit(-1); } Echo Client The client application takes the server TCP port and IP address on the command line. For each connection a string is displayed and sent to the server, the echoed string is received back and displayed, then the connection is closed. The client will be defined in the file client.cpp #include #include #include #include "tcpconnector.h" using namespace std; int main(int argc, char** argv) { if (argc != 3) {
  • 13. printf("usage: %s ", argv[0]); exit(1); } int len; string message; char line[256]; TCPConnector* connector = new TCPConnector(); TCPStream* stream = connector->connect(argv[2], atoi(argv[1])); if (stream) { message = "Is there life on Mars?"; stream->send(message.c_str(), message.size()); printf("sent - %s ", message.c_str()); len = stream->receive(line, sizeof(line)); line[len] = NULL; printf("received - %s ", line); delete stream; } stream = connector->connect(argv[2], atoi(argv[1])); if (stream) { message = "Why is there air?"; stream->send(message.c_str(), message.size()); printf("sent - %s ", message.c_str()); len = stream->receive(line, sizeof(line)); line[len] = NULL; printf("received - %s ", line); delete stream; } exit(0); } #include #include #include #include using namespace std class TCPStream {
  • 14. int m_sd; string m_peerIP; int m_peerPort; public: friend class TCPAcceptor; friend class TCPConnector; ~TCPStream(); ssize_t send(char* buffer, size_t len); ssize_t receive(char* buffer, size_t len); string getPeerIP(); int getPeerPort(); private: TCPStream(int sd, struct sockaddr_in* address); TCPStream(); TCPStream(const TCPStream& stream); };