Wyv9
?Dy ù?
C Network Application Development
Client Software Design 1
Chapter 3: Client Software Design
Chapter goal:
? Algorithm and issues
? Concurrency in client
? Client examples
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 2
Chapter 3: Client Software Design
Chapter goal:
? Algorithm and issues
? Concurrency in client
? Client examples
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 3
Learning algorithm instead of
details
? An application that uses TCP/IP must specify many
details about the desired communication.
? Knowing the low-level details of all possible socket
functions and their exact parameters does not provide
programmers with an understanding of how to build
well-designed, distributed program.
? General understanding of the functions used for
network communication is important.
? If the programmer knows what the program should do,
finding out how to do it is straightforward.
? Although programmers need to understand the
conceptual capabilities of the protocol interface, they
should concentrate on learning about ways to structure
communicating programs instead of memorizing the
details of a particular interface.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 4
Client architecture
? Clients are conceptually simpler than
servers.
? Most client does not explicitly handle
concurrent interaction with multiple servers.
? Most client executes as a conventional app
program.
? Most client does not need to enforce
protections.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 5
Identify a server
? Several methods to find a server’s IP address and
protocol port number:
? Domain name or IP address as a constant in program;
? Requiring user to identify;
? From stable storage;
? Using a separate protocol to find;
? Allowing the user to specify a server address when
invoking client software makes the client program
more general and makes it possible to change server
locations.
? Building client that accepts a server address as an
argument makes it easy to build extended versions
of the software that use other ways to find the
server address.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 6
Parsing an address argument
? Client can use domain name or IP address to
identify the server machine.
? To determine whether the user has specified
a name or an address, the client scans the
argument.
? Client sometimes need additional information,
such as protocol port.
? Two arguments:
merlin.cs.purdue.edu smtp
? Single argument:
merlin.cs.purdue.edu:smtp
? Consistency is important
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 7
Looking up a domain name
? A client must specify the address of a server using
structure of sockaddr_in.
? Doing so means converting an address in dotted
decimal notation (or domain name) into a 32-bit IP
address.
? Function inet_addr takes an ASCII string that
contains a dotted decimal address and returns the
equivalent IP address in binary.
? Function gethostbyname takes an ASCII string that
contains the domain name for a machine, and returns
the address of a hostent structure that contains,
among other strings, the host’s IP address in binary.
? The hostent structure is declared in include file
winsock.h.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 8
hostent structure
stuct hostent {
char FAR* h_name; /*official host name */
char FAR* FAR* h_aliases; /*other aliases */
short h_addrtype; /*address type */
short h_lengty; /*address length */
char FAR* FAR* h_addr_list; /*list of address */
};
#define h_addr h_addr_list[0]
? Fields that contain names and addresses must be lists because
of multiple interfaces.
? h_addr refer to the first location in the host address list.
? A program can use h_addr as if it were a field of structure
hostent.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 9
Example for gethostbyname
stuct hostent *hptr;
char *examplenam=“merlin.cs.purdue.edu”;
if (hptr=gethostbyname(example)){
/* IP address is now in hptr->h_addr*/
}else {
/*error in name-handle it*/
}
? Successfully call, gethostbyname returns a pointer
to a valid hostent struture. Otrerwise,
? Returns a NULL pointer.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 10
Looking up a well-known port by
name
? Look up the protocol port for specific
service.
? getservbyname
? Two arguments:
? A string that specifies the desired service
? A string that specifies the protocol being used
? Returns a pointer to a structure of type
servent.
? Defined in include file winsock.h.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 11
servent structure
stuct servent {
char FAR* s_name; /*official service name */
char FAR* FAR* s_aliases; /*other aliases */
short s_port; /*port for this service */
char FAR* s_proto; /*protocol to use */
};
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 12
Example
stuct servent *sptr;
if (sptr=getservbyname(“smtp”, “tcp”)){
/* port number is now in sptr->s_port*/
}else {
/*error occurred-handle it*/
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 13
Port numbers and network byte
order
? getservbyname returns the protocol port
for the service in network byte order.
? It is sufficient to understand that
getservbyname returns the port value in
exactly the form needed for use in the
sockaddr_in structure.
? But, the representation may not agree with
the local machine’s usual representation.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 14
Looking up a protocol by name
? getprotobyname returns the address of a
structure of type protoent.
? Contained in winsock.h.
stuct protoent {
char FAR* p_name; /*official protocol name */
char FAR* FAR* p_aliases; /*list of aliases allowed*/
short p_proto; /*official protocol number*/
};
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 15
Example
stuct protoent *pptr;
if (pptr=getprotobyname(“udp”)){
/* official protocol number is now in pptr->p_proto*/
}else {
/*error occurred-handle it*/
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 16
The TCP client algorithm
1. Find the IP address and protocol port number
of the server with which communication is
desired.
2. Allocate a socket.
3. Specify that the connection needs an arbitrary,
unused protocol port on the local machine, and
allow TCP to choose one.
4. Connect the socket to the server.
5. Communicate with the server using the
application-layer protocols.
6. Close the connection.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 17
Allocating a socket
#include <winsock.h>
SOCKET s;
s=socket(PF_INET, SOCK_STREAM, 0 );
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 18
Choosing a local protocol port
number
? The client does not care which port it uses
as long as :
? The port does not conflict with the ports that
other applications on the machine are already
using.
? The port has not been assigned to a well-known
service.
? The choice of a local port that meets the
criteria listed above happens as a side-
effect of the connect call.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 19
Choosing a local IP address
? A client must choose a local IP address as well as a
local port number.
? Gateways (routers) or multihomed hosts have
multiple IP addresses.
? The difficulty in choosing an IP address arises
because the correct choice depends on routing and
applications seldom have access to routing
information.
? Problem: the IP source address in an outgoing
datagram should match the IP address of the
network interface over which IP routes the
datagram.
? Using an incorrect address violates the specification,
makes network management difficult and confusing,
and makes the program less reliable.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 20
Choosing a local IP address
? To solve the problem, the socket functions make it
possible for an application to leave the local IP
address field unfilled and to allow TCP/IP software
to choose a local IP address automatically at the
time the client connects to a server.
? Because choosing the correct local IP address
requires the application to interact with IP routing
software, TCP client software usually leaves the
local endpoint address unfilled, and allows TCP/IP
software to select the correct local IP address and
an unused local protocol port number automatically.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 21
Connecting a TCP socket to a
server
? connect function
? connect forces the initial TCP 3-way
handshaking.
? The call to connect does not return until a
TCP connection has been established or TCP
reaches timeout threshold and gives up.
? The call returns 0 if the connection attempt
succeeds or SOCKET_ERROR if it fails.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 22
Connecting a TCP socket to a
server
connect(socket,remaddr,remaddrlen);
? Socket is the descriptor for a socket;
? Remaddr is the address of a structure of
type sockaddr_in that specifies the remote
endpoint to which a connection is desired;
? Remaddrlen is the length of remaddr.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 23
Connecting a TCP socket to a
server
? connect performs four tasks:
? Test to ensure that the specified socket is valid
and that it has not already been connected;
? Fills in the remote endpoint address in the socket
from the second argument;
? Chooses a local endpoint address for the
connection (IP address and protocol port number)
if the socket does not have one;
? Initiates a TCP connection, and returns a value to
tell the caller whether the connection succeeded.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 24
Communicating with the server
using TCP
? Usually request-response interaction.
? A client call send to transmit each request
and recv to await a response.
? For example:
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 25
Communicating with the server
using TCP
#define BLEN 120 /*buffer length to use */
char *req=“request of some sort”;
char buf[BLEN]; /*buffer for answer */
char *bptr; /*pointer to buffer */
int n; /*number of bytes read */
int buflen; /*space left in buffer */
Bptr=buf;
buflen=BLEN;
/*send request*/
send(s,req,strlen(req),0);
/*read response (may come in many pieces)*/
n=recv(s,bptr,buflen,0);
while(n!=SOCKET_ERROR && n!=0){
bptr+=n;
buflen-=n;
n=recv(s,bptr,buflen,0);
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 26
Reading response from a TCP
connection
? TCP is not a block-oriented protocol, is a
stream-oriented protocol.
? TCP guarantees to deliver the sequence of bytes
that the sender writes, but it does not guarantee
to deliver them in the same grouping as they were
wirten.
? Because TCP does not preserve record
boundaries, any program that reads from a
TCP connection must be prepared to accept
data a few bytes at a time.
? This rule holds even if the sending application
writes data in large blocks.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 27
Closing a TCP connection
? closesocket terminates the connection
gracefully and deallocate the socket.
? Closing a connection is not simple because of
full-duplex.
? Closing a connection usually requires
coordination among the client and server.
? To solve the connection shutdown problem,
most implementations of the socket interface
include an additional primitive that permits
application to shut down a TCP connection in
one direction.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 28
A partial close operation
? shutdown function takes two parameters:
? A socket descriptor
? Direction
errcode = shutdown( s, direction);
Integer:
0-no further input is allowed;
1-no further output is allowed;
2-both direction.
? Advantage: end-of-file signal.
? The partial close mechanism removes ambiguity for
application protocols that transmit arbitrary amounts of
information in response to a request.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 29
Programming a UDP client-
algorithm
1. Find the IP address and protocol port number
of the server with which communication is
desired.
2. Allocate a socket.
3. Specify that the communication needs an
arbitrary, unused protocol port on the local
machine, and allow UDP to choose one.
4. Specify the server which messages to sent.
5. Communicate with the server using the
application-layer protocol.
6. Close the connection.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 30
Connected and unconnected UDP
sockets
? Two basic UDP socket mode:
? Connected
? Unconnected
? Advantages:
? Connected: the application need specify the server only once.
? Unconnected: flexibility, communicate with different
servers.
? UDP sockets can be connected, making it conventional
to interact with a specific server, or they can be
unconnected, making it necessary for the application
to specify the server’s address each time it sends a
message.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 31
Using connect with UDP
? The connect call does not initiate any packet
exchange, nor does it test the validity of the
remote endpoint address.
? It merely records the remote endpoint
information in the socket data structure for
later use.
? Even if connect call succeeds, it does not
mean that the remote endpoint address is
valid or that the server if reachable.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 32
Communicating with a server
using UDP
? UDP provides message transfer.
? Connect mode
? Using send and recv to send or receive a
message.
? UDP client does not need to make
repeated calls to recv to obtain a single
message.
? UDP does not need repeated call to recv
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 33
Closing a socket that uses UDP
? Calls closesocket like TCP, but does not
inform the remote endpoint.
? Partial close for UDP
? shutdown can be used with a connected UDP
socket to stop further transmission in a given
direction.
? Unlike TCP, shutdown does not send any
messages to the other side.
? It merely marks the local socket as unwilling
to transfer data in the direction(s) specified.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 34
About UDP unreliability
? Client software that uses UDP must
implement reliability with techniques like
packet sequencing, acknowledgements,
timeout, and efficient for an internet
environment requires consideration
expertise.
? How to build reliable apps over UDP?
? Home work……
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 35
Chapter 3: Client Software Design
Chapter goal:
? Algorithm and issues
? Concurrency in client
? Client examples
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 36
Advantages of concurrency
? Server
? Response time
? Potential deadlocks
? Multiprotocol & multiservice servers
? portability
? Client
? Easier to program: Separate functionality into conceptually
separate components
? Easier to maintain and extend: modular
? Can contact several servers at the same time
? Allow users to change parameters, inquire about the client
status, or control processing dynamically
? The key advantage lies in asynchrony.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 37
Motivation for exercising control
? Separate control functions from normal processing
? Uncertain response time and response size
? Most client merely waits until a response arrives
? Deadlock may occur
? Concurrency can help
? Concurrent client can permit user to continue interact with
the client while the client waits for a response
? User can find out whether any data has been received,
choose to send a different request, or terminate
? Separating client control from normal processing
allows a user to interact with a client even if the
normal input for the client comes from a file.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 38
Concurrent contact with multiple
servers
? Concurrency can allow a single client to
contact several servers at the same time and
report to the user as soon as it receives from
any of them
? For example
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 39
Implementing concurrent clients
? Two basic approaches
? The client divides into two or more threads
that each handle one function
? The client consists of a single thread that uses
select to handle multiple input and output
events asynchronously
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 40
Implementing concurrent clients
? Two basic approaches
? The client divides into two or more threads that each handle
one function
? The client consists of a single thread that uses select to
handle multiple input and output events asynchronously
control
input output
Control
descriptor
input TCP
socket
output
Client threads
Operating system
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 41
Implementing concurrent clients
? Two basic approaches
? The client divides into two or more threads that each handle
one function
? The client consists of a single thread that uses select to
handle multiple input and output events asynchronously
client
input
TCP
socket
1
TCP
socket
2
TCP
socket
n
Client thread
Operating system
…
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 42
Chapter 3: Client Software Design
Chapter goal:
? Algorithm and issues
? Concurrency in client
? Client examples
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 43
Example client software
? Importance of small
examples
? Easy to understand
? Highlight fundamental
algorithm
? Intuitive understanding
? Hiding details
? Modular program
? Easy to port
? Procedures raise the level of
the language-reuse
? Use of procedures is important
when building C/S programs
? Reduce the chance for error
? Reuse the code
? Isolate the OS dependency
? The first step of
designing a
procedure lib is
abstraction
? The procedure
abstraction allows
programmers to
define high-level
operations, share
code among
applications.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 44
Implementation of ConTCP
/* conTCP.cpp - connectTCP */
#include <winsock.h>
SOCKET connectsock(const char *, const char *,
const char *);
/*----------------------------------------------------
* connectTCP - connect to a specified TCP service
* on a specified host
*-------------------------------------------------- */
SOCKET
connectTCP(const char *host, const char *service )
{
return connectsock( host, service, "tcp");
}
? Place all the
low level
code into
connectsock
procedure
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 45
Implementation of ConUDP
/* conUDP.cpp - connectUDP */
#include <winsock.h>
SOCKET connectsock(const char *, const char *,
const char *);
/*-------------------------------------------------------
* connectUDP - connect to a specified UDP service
* on a specified host
*-----------------------------------------------------*/
SOCKET
connectUDP(const char *host, const char *service )
{
return connectsock(host, service, "udp");
}
? Used to
establish a
connected
socket that
uses UDP
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 46
A procedure that forms
connections
/* consock.cpp - connectsock */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <winsock.h>
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif /* INADDR_NONE */
void errexit(const char *, ...);
/*------------------------------------------------------------------------
* connectsock - allocate & connect a socket using TCP or UDP
*------------------------------------------------------------------------
*/
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 47
A procedure that forms
connections (cont.)
SOCKET
connectsock(const char *host, const char *service, const char *transport )
{
struct hostent *phe; /* pointer to host information entry */
struct servent *pse; /* pointer to service information entry */
struct protoent *ppe; /* pointer to protocol information entry */
struct sockaddr_in sin;/* an Internet endpoint address */
int s, type; /* socket descriptor and socket type */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 48
A procedure that forms
connections (cont.)
/* Map service name to port number */
if ( pse = getservbyname(service, transport) )
sin.sin_port = pse->s_port;
else if ( (sin.sin_port = htons((u_short)atoi(service))) == 0 )
errexit("can't get \"%s\" service entry\n", service);
/* Map host name to IP address, allowing for dotted decimal */
if ( phe = gethostbyname(host) )
memcpy(&sin.sin_addr, phe->h_addr, phe->h_length);
else if ( (sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
errexit("can't get \"%s\" host entry\n", host);
/* Map protocol name to protocol number */
if ( (ppe = getprotobyname(transport)) == 0)
errexit("can't get \"%s\" protocol entry\n", transport);
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 49
A procedure that forms
connections (cont.)
/* Use protocol to choose a socket type */
if (strcmp(transport, "udp") == 0)
type = SOCK_DGRAM;
else
type = SOCK_STREAM;
/* Allocate a socket */
s = socket(PF_INET, type, ppe->p_proto);
if (s == INVALID_SOCKET)
errexit("can't create socket: %d\n", GetLastError());
/* Connect the socket */
if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) ==
SOCKET_ERROR)
errexit("can't connect to %s.%s: %d\n", host, service,
GetLastError());
return s;}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 50
A procedure that forms
connections (cont.)
/* errexit.cpp - errexit */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
/*------------------------------------------------------------------------
* errexit - print an error message and exit
*------------------------------------------------------------------------ */
/*VARARGS1*/
void errexit(const char *format, ...)
{ va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
va_end(args);
WSACleanup();
exit(1);}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 51
Client examples-1
? The DAYTIME service
? Obtain the day and time
? Available for both TCP and UDP, port 13
? The TCP version uses the presence of a TCP
connection to trigger output
? The UDP version needs the client to send a
request
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 52
Implementation of a TCP client
for DAYTIME
/* TCPdtc.cpp - main, TCPdaytime */
#include <stdlib.h>
#include <stdio.h>
#include <winsock.h>
void TCPdaytime(const char *, const char *);
void errexit(const char *, ...);
SOCKET connectTCP(const char *, const char *);
#define LINELEN 128
#define WSVERS MAKEWORD(2, 0)
/*------------------------------------------------------------------------
* main - TCP client for DAYTIME service
*------------------------------------------------------------------------
*/
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 53
Implementation of a TCP client
for DAYTIME (cont.)
Int main(int argc, char *argv[])
{
char *host = "localhost"; /* host to use if none supplied */
char *service = "daytime"; /* default service port */
WSADATA wsadata;
switch (argc) {
case 1:
host = "localhost";
break;
case 3:
service = argv[2];
/* FALL THROUGH */
case 2:
host = argv[1];
break;
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 54
Implementation of a TCP client
for DAYTIME (cont.)
default:
fprintf(stderr, "usage: TCPdaytime [host [port]]\n");
exit(1);
}
if (WSAStartup(WSVERS, &wsadata) != 0)
errexit("WSAStartup failed\n");
TCPdaytime(host, service);
WSACleanup();
return 0; /* exit */
}
/*------------------------------------------------------------------------
* TCPdaytime - invoke Daytime on specified host and print results
*------------------------------------------------------------------------
*/
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 55
Implementation of a TCP client
for DAYTIME (cont.)
void TCPdaytime(const char *host, const char *service)
{
char buf[LINELEN+1]; /* buffer for one line of text */
SOCKET s; /* socket descriptor */
int cc; /* recv character count */
s = connectTCP(host, service);
cc = recv(s, buf, LINELEN, 0);
while( cc != SOCKET_ERROR && cc > 0) {
buf[cc] = '\0'; /* ensure null-termination */
(void) fputs(buf, stdout);
cc = recv(s, buf, LINELEN, 0);
}
closesocket(s);
}
Because the TCP stream service does not
guarantee to deliver data in the same blocks
that it was writen, an application receiving
data from a TCP connection cannot depend
on all data being delivered in a single
transfer; it must repeatedly call recv until all
data has been obtained.
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 56
Client examples-2
? The TIME service
? Obtain the day and time from another machine similar to
DAYTIME service
? Time and day information must be represented in
Universal Coordinated Time
? TIME service is intended for use by programs that store
or manipulate times
? Always specifies time in a 32-bit integer, representing
the number of seconds since an epoch date
? TIME Uses midnight, January 1, 1900, as its epoch
? Available for both TCP and UDP, port 37
? The TCP version uses the presence of a TCP connection
to trigger output
? The UDP version needs the client to send a request
? TIME does not handle the problem of network latency
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 57
A UDP Client for the TIME
service
/* UDPtime.cpp - main */
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <winsock.h>
#define BUFSIZE 64
#define WSVERS MAKEWORD(2, 0)
#define WINEPOCH 2208988800 /* Windows epoch, in UCT secs */
#define MSG "what time is it?\n"
SOCKET connectUDP(const char *, const char *);
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 58
A UDP Client for the TIME
service (cont.)
void errexit(const char *, ...);
/*------------------------------------------------------------------------
* main - UDP client for TIME service that prints the resulting time
*------------------------------------------------------------------------
*/
int main(int argc, char *argv[])
{
char *host = "localhost"; /* host to use if none supplied */
char *service = "time"; /* default service name */
time_t now; /* 32-bit integer to hold time */
SOCKET s; /* socket descriptor */
int n; /* recv count */
WSADATA wsadata;
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 59
A UDP Client for the TIME
service (cont.)
switch (argc) {
case 1:
host = "localhost";
break;
case 3:
service = argv[2];
/* FALL THROUGH */
case 2:
host = argv[1];
break;
default:
fprintf(stderr, "usage: UDPtime [host [port]]\n");
exit(1);
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 60
A UDP Client for the TIME
service (cont.)
if (WSAStartup(WSVERS, &wsadata))
errexit("WSAStartup failed\n");
s = connectUDP(host, service);
(void) send(s, MSG, strlen(MSG), 0);
/* Read the time */
n = recv(s, (char *)&now, sizeof(now), 0);
if (n == SOCKET_ERROR)
errexit("recv failed: recv() error %d\n", GetLastError());
WSACleanup();
now = ntohl((u_long)now); /* put in host byte order */
now -= WINEPOCH; /* convert UCT to Windows epoch*/
printf("%s", ctime(&now));
return 0; /* exit */
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 61
Client examples-3
? The ECHO service
? ECHO service for both TCP and UDP port 7
? Merely returns all the data received from a
client
? Important tools for:
? Test reachability
? Debug protocol software
? Identify routing problem
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 62
A TCP Client for the ECHO
service
/* TCPecho.cpp - main, TCPecho */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <winsock.h>
void TCPecho(const char *, const char *);
void errexit(const char *, ...);
SOCKET connectTCP(const char *, const char *);
#define LINELEN 128
#define WSVERS MAKEWORD(2, 0)
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 63
A TCP Client for the ECHO
service (cont.)
/*------------------------------------------------------------------------
* main - TCP client for ECHO service
*----------------------------------------------------------------------- */
void main(int argc, char *argv[])
{
char *host = "localhost"; /* host to use if none supplied */
char *service = "echo"; /* default service name */
WSADATA wsadata;
switch (argc) {
case 1:
host = "localhost";
break;
case 3:
service = argv[2];
/* FALL THROUGH */
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 64
A TCP Client for the ECHO
service (cont.)
case 2:
host = argv[1];
break;
default:
fprintf(stderr, "usage: TCPecho [host [port]]\n");
exit(1);
}
if (WSAStartup(WSVERS, &wsadata) != 0)
errexit("WSAStartup failed\n");
TCPecho(host, service);
WSACleanup();
exit(0);
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 65
A TCP Client for the ECHO
service (cont.)
/*------------------------------------------------------------------------
* TCPecho - send input to ECHO service on specified host and print reply
*------------------------------------------------------------------------ */
void TCPecho(const char *host, const char *service)
{
char buf[LINELEN+1]; /* buffer for one line of text */
SOCKET s; /* socket descriptor */
int cc, outchars, inchars; /* characters counts */
s = connectTCP(host, service);
while (fgets(buf, sizeof(buf), stdin)) {
buf[LINELEN] = '\0'; /* ensure line null-termination */
outchars = strlen(buf);
(void) send(s, buf, outchars, 0);
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 66
A TCP Client for the ECHO
service (cont.)
/* read it back */
for (inchars = 0; inchars < outchars; inchars += cc) {
cc = recv(s, &buf[inchars], outchars-inchars, 0);
if (cc == SOCKET_ERROR)
errexit("socket recv failed: %d\n",
GetLastError());
}
fputs(buf, stdout);
}
closesocket(s);
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 67
A UDP Client for the ECHO
service
/* UDPecho.cpp - main, UDPecho */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <winsock.h>
void UDPecho(const char *, const char *);
void errexit(const char *, ...);
SOCKET connectUDP(const char *, const char *);
#define LINELEN 128
#define WSVERS MAKEWORD(2, 0)
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 68
A UDP Client for the ECHO
service (cont.)
/*------------------------------------------------------------------------
* main - UDP client for ECHO service
*------------------------------------------------------------------------ */
void main(int argc, char *argv[])
{
char *host = "localhost";
char *service = "echo";
WSADATA wsadata;
switch (argc) {
case 1:
host = "localhost";
break;
case 3:
service = argv[2];
/* FALL THROUGH */
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 69
A UDP Client for the ECHO
service (cont.)
case 2:
host = argv[1];
break;
default:
fprintf(stderr, "usage: UDPecho [host [port]]\n");
exit(1);
}
if (WSAStartup(WSVERS, &wsadata))
errexit("WSAStartup failed\n");
UDPecho(host, service);
WSACleanup();
exit(0);
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 70
A UDP Client for the ECHO
service (cont.)
/*------------------------------------------------------------------------
* UDPecho - send input to ECHO service on specified host and print reply
*------------------------------------------------------------------------ */
void UDPecho(const char *host, const char *service)
{
char buf[LINELEN+1]; /* buffer for one line of text */
SOCKET s; /* socket descriptor */
int nchars; /* read count*/
s = connectUDP(host, service);
while (fgets(buf, sizeof(buf), stdin)) {
buf[LINELEN] = '\0'; /* ensure null-terminated */
nchars = strlen(buf);
(void) send(s, buf, nchars, 0);
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 71
A UDP Client for the ECHO
service (cont.)
if (recv(s, buf, nchars, 0) < 0)
errexit("recv failed: error %d\n",
GetLastError());
fputs(buf, stdout);
}
}
? Find out the difference between TCP and
UDP version?
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 72
Concurrent Client example
? An example concurrent client that uses
ECHO service
? Single thread
? Uses the ECHO service to measure network
throughput to a set of machines
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 73
Concurrent client
/* TCPtecho.cpp - main, TCPtecho, reader, writer, mstime */
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <winsock.h>
#define BUFSIZE 4096 /* write buffer size */
#define CCOUNT 64*1024 /* default character count */
#define WSVERS MAKEWORD(2, 0)
#define MIN(x, y) ((x)>(y) ? (y) : (x))
#define USAGE "usage: TCPtecho [ -c count ] host1 host2...\n"
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 74
Concurrent client (cont.)
struct hdat {
char *hd_name; /* host name */
SOCKET hd_sock; /* host socket descriptor */
unsigned hd_rc; /* recv character count */
unsigned hd_wc; /* send character count */
} hdat[FD_SETSIZE]; /* fd to host name mapping */
char buf[BUFSIZE]; /* read/write data buffer */
void TCPtecho(fd_set *, int);
int reader(struct hdat *, fd_set *);
void writer(struct hdat *, fd_set *);
void errexit(const char *, ...);
SOCKET connectTCP(const char *, const char *);
long mstime(u_long *);
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 75
Concurrent client (cont.)
/*------------------------------------------------------------------------
* main - concurrent TCP client for ECHO service timing
*------------------------------------------------------------------------ */
void main(int argc, char *argv[])
{
int ccount = CCOUNT;
int i, hcount, fd;
unsigned long one = 1;
fd_set afds;
WSADATA wsdata;
hcount = 0;
if (WSAStartup(WSVERS, &wsdata))
errexit("WSAStartup failed\n");
FD_ZERO(&afds);
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 76
Concurrent client (cont.)
for (i=1; i<argc; ++i) {
if (strcmp(argv[i], "-c") == 0) {
if (++i < argc && (ccount = atoi(argv[i])))
continue;
errexit(USAGE);
}
/* else, a host */
fd = connectTCP(argv[i], "echo");
if (ioctlsocket(fd, FIONBIO, &one)) {
fprintf(stderr,
"can't mark nonblocking (host %s): %d\n",
argv[i], GetLastError());
continue;
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 77
Concurrent client (cont.)
hdat[hcount].hd_name = argv[i];
hdat[hcount].hd_sock = fd;
hdat[hcount].hd_rc = hdat[hcount].hd_wc = ccount;
++hcount;
FD_SET(fd, &afds);
}
TCPtecho(&afds, hcount);
WSACleanup();
exit(0);
}
/*------------------------------------------------------------------------
* TCPtecho - time TCP ECHO requests to multiple servers
*----------------------------------------------------------------------*/
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 78
Concurrent client (cont.)
void TCPtecho(fd_set *pafds, int hcount)
{
fd_set rfds, wfds; /* read/write fd sets */
fd_set rcfds, wcfds; /* read/write fd sets (copy) */
int fd, hndx, i;
for (i=0; i<BUFSIZE; ++i) /* echo data */
buf[i] = 'D';
memcpy(&rcfds, pafds, sizeof(rcfds));
memcpy(&wcfds, pafds, sizeof(wcfds));
(void) mstime((u_long *)0); /* set the epoch */
while (hcount) {
memcpy(&rfds, &rcfds, sizeof(rfds));
memcpy(&wfds, &wcfds, sizeof(wfds));
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 79
Concurrent client (cont.)
if (select(FD_SETSIZE, &rfds, &wfds, (fd_set *)0,
(struct timeval *)0) == SOCKET_ERROR)
errexit("select failed: error %d\n",
GetLastError());
for (hndx=0; hndx<hcount; ++hndx) {
fd = hdat[hndx].hd_sock;
if (FD_ISSET(fd, &rfds))
if (reader(&hdat[hndx], &rcfds) == 0) {
/* this host is done */
for (i=hndx+1; i<hcount; ++i)
hdat[i-1]=hdat[i];
hcount--;
continue;
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 80
Concurrent client (cont.)
if (FD_ISSET(fd, &wfds))
writer(&hdat[hndx], &wcfds);
}
}
}
/*------------------------------------------------------------------------
* reader - handle ECHO reads
*------------------------------------------------------------------------ */
int reader(struct hdat *phd, fd_set *pfdset)
{
u_long now;
int cc;
cc = recv(phd->hd_sock, buf, sizeof(buf), 0);
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 81
Concurrent client (cont.)
if (cc == SOCKET_ERROR)
errexit("recv: error %d\n", GetLastError());
if (cc == 0)
errexit("recv: premature end of file\n");
phd->hd_rc -= cc;
if (phd->hd_rc > 0)
return 1;
(void) mstime(&now);
printf("%s: %d ms\n", phd->hd_name, now);
(void) closesocket(phd->hd_sock);
FD_CLR(phd->hd_sock, pfdset);
return 0;
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 82
Concurrent client (cont.)
/*------------------------------------------------------------------------
* writer - handle ECHO writes
*------------------------------------------------------------------------ */
void writer(struct hdat *phd, fd_set *pfdset)
{
int cc;
cc = send(phd->hd_sock, buf, MIN(sizeof(buf), phd->hd_wc), 0);
if (cc == SOCKET_ERROR)
errexit("send: error number %d\n", GetLastError());
phd->hd_wc -= cc;
if (phd->hd_wc == 0) {
(void) shutdown(phd->hd_sock, 1);
FD_CLR(phd->hd_sock, pfdset);
}
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 83
Concurrent client (cont.)
/*------------------------------------------------------------------------
* mstime - report the number of clock ticks elapsed since mstime(0) call
*------------------------------------------------------------------------ */
long mstime(u_long *pms)
{
static unsigned long epoch;
unsigned long now;
now = clock();
if (pms == 0) {
epoch = now;
return 0;
}
*pms = now - epoch;
return *pms;
}
Wyv9
?Dy ù?
C Network Application Development
Client Software Design 84
Summary
We have Learned:
? Algorithm and issues
? Concurrency in client
? Client examples