Vous êtes sur la page 1sur 30

Client designs

Connection-oriented clients
Connectionless clients

Client examples
TCP DAYTIME
UDP TIME
TCP and UDP ECHO
host
entry
ip address
(32b)
ip address
dot.decimal
gethostbyname
gethostbyaddr
inet_aton
service
entry
port #
(16b)
getservbyname
protocol
entry
portocol # getprotobyname
getsockname
getsockopt
setsockopt
hostent
addr type
name
alias
length
addr list
icmp 1
igmp 2
tcp 6
udp 17
rsvp 46
sctp 132
raw 255
servent
port
name
alias list
protocol
protoent
protocol #
name
alias list
http 80
dns 53
smtp 25
telnet 23
daytime 13
ftp 21
Domain Name System (DNS)
System configuration files, e.g.
/etc/hosts, /etc/services, /etc/resolv.conf

Convert between names and numeric values
gethostbyname() and gethostbyaddr()
Convert between hostnames and IPv4 addresses
getservbyname() and getservbyport()
Convert between service names and port numbers
getaddrinfo() and getnameinfo()
Two protocol-independent functions
Convert between hostnames and IP addresses and
between service names and port numbers
Typical arrangement of clients, resolvers and
name servers
/etc/resolv.conf
(IP addresses of
local name servers)
#include <netdb.h>
struct hostent *gethostbyname(const char *hostname);

struct hostent {
char *h_name; /* official (canonical) name of host */
char **h_aliases; /* ptr to array of ptrs to alias names */
int h_addrtype; /* host address type: AF_INET */
int h_length; /* length of address: 4 */
char **h_addr_list; /* ptr to array of ptrs with IPv4 addrs */
}
#include <netdb.h>
struct servent *getservbyname(const char *servname,
const char *protoname);
struct servent *getservbyport(int port,
const char *protoname);

struct servent {
char *s_name; /* official service name */
char **s_aliases; /* aliases list */
int s_port; /* port number, network byte order */
int s_proto; /* protocol to use */
}
struct servent *sptr;

sptr = getservbyname(domain, udp); // DNS using UDP
sptr = getservbyname(ftp, tcp); // FTP using tCP
sptr = getservbyname(ftp, udp); // This call will fail

sptr = getservbyport(htons(21), tcp); // FTP using TCP
sptr = getservbyport(htons(21), NULL); // FTP using TCP
sptr = getservbyport(htons(21), udp); // This call will fail
1. Find the IP address and protocol port
number of the server
2. Allocate a socket
3. Specify the local port number or allow TCP
to choose one
4. Connect the socket to the server
5. Communicate with the server
6. Close the connection
1a) Find servers IP address
Converting from dotted decimal to 32-bit binary
notation
#include <arpa/inet.h>
int inet_aton(const char *strp, struct in_addr *inp);
in_addr_t inet_addr(const char *strp); // deprecated

Converting from symbolic name to 32-bit binary
notation
#include <netdb.h>
struct hostent *gethostbyname(const char *hostname);

1b) Find servers port number by service
#include <netdb.h>
struct servent *getservbyname(const char *name,
const char *protoname);
name desired service name, e.g. smtp
protoname transport protocol being used, e.g. tcp

2. Allocate a socket
#include <sys/types.h>
#include <sys/socket.h>
int sd; /* socket descriptor */

sd = socket(PF_INET, SOCK_STREAM, 0);
// valid only if sd > 0

3. Specify local port # or allow TCP to choose one
Which port number is right for client?
Users may choose the specific port
Dont have to use a known port number
Possible, cause an error if the port is in use

struct sockaddr_in sockinfo;
sockinfo.sin_port = htons(8000);

Or let the system choose one (recommended)
sockinfo.sin_port = htons(0);

4. Connect the socket to the server
#include <sys/socket.h>
int connect(int sockfd,
const struct sockaddr *servaddr,
socklen_t addrlen);

What does it do?
Ensure socket is valid and unconnected
Enter remote endpoint into socket descriptor table
Select and enter local endpoint information
Complete 3-way handshake and establish TCP
connection
Why there is no source address specified in
the interface?
The system chooses the right IP address for you
Otherwise, users should figure out it if there are
multiple network interfaces available
Not sure which IP address should be used in the local
address
Wrong address could result in inefficient routing
causing significant delays
5. Communicate with the server
Reading from the connection
recv(socket, msg, msglen, flags) or
read(socket, msg, msglen)
Writing into the TCP connection
send(socket, msg, msglen, flags) or
write(socket, msg, msglen)
TCP is a stream oriented protocol
TCP packets could be fragmented during transmission





Need to loop until all the data are received
n = recv(sd, buf, buflen, 0);
while (n != SOCKET_ERROR && n != 0) {
buf += n;
buflen -= n;
n = recv(sd, buf, buflen, 0);
}
6. Close the connection
What if there are outstanding data to
send/receive when closing the connection?
Better coordination: Partial close
#include <sys/socket.h>
int shutdown(int sockfd, int howto);

SHUT_RD no further reception allowed
SHUT_WR no further transmission allowed
SHUT_RDWR no further receptions & transmission allowed
close()
Only closes the socket ID for the process
Leaves the connection open if there is another
process using the same socket

shutdown()
Breaks the connection for all the processes using
the socket
sd = connect();
if (fork() == 0) { /* Child: send input */
while (gets(buf) > 0) {
write(sd, buf, strlen(buf));
}
close(sd);
exit(0);
} else { /* Parent: read from server */
while ((datalen = read(sd, buf, buflen)) > 0) {
do_something(buf, datalen);
}
wait(0);
exit(0);
}

sd is used by both read and write processes.
1. Find the IP address and protocol port
number of the server
Similar to connection-oriented clients
2. Allocate a socket
socket(PF_INET, SOCK_DGRAM, 0);
3. Specify the local port number or allow UDP
to choose one
Like connection-oriented clients
4. Specify the server to which the message is
sent
5. Communicate with the server
Unconnected UDP sockets
Connected UDP sockets
6. Close the socket or partial close the socket
Socket is NOT tied to a specific server
Should specify remote address every time called
Can interact with multiple servers

sendto(socket, msg, msglen, flags, to, tolen)
recvfrom(socket, buf, buflen, flags,
from, fromlen)

The socket is tied to a specific server after
connect call
Remote endpoint info is stored in socket descriptor
table
Dont have to specify remote address every time called
recv() and send() can be used
Interact with only one server
What should be different? What should be
careful in UDP programming?
What if the packet is dropped?
What if the packet is delivered in out of order?
For reliability
Packet sequencing
Acknowledgements
Timeouts
Retransmission
DAYTIME service
TCP client for DAYTIME

TIME service
UDP client for the TIME service

ECHO service
TCP and UDP clients for the ECHO service

Use common procedures
connectTCP(host, service)
connectUDP(host, service)
connectsock(host, service, transport)
errexit(format, )
Available as TCP and UDP services at port 13
How to support both TCP and UDP services?
E.g. select(), multi-threaded, or multi-process
select()
Poll multiple file/socket descriptors
Allow to handle whichever comes available first
Server sends daytime as a character string
Example:
Wednesday, September 10, 2014 18:30:40-PDT
TCP version
Server sends daytime message whenever it accepts
a connection
UDP version
Server sends daytime message whenever it receives
a datagram
Example code
TCPdaytime.c in the textbook
Available as TCP and UDP services at port 37
Server responds with time in Universal
Coordinated Time (UCT)
32-bit integer as the number of seconds since
January 1, 1900.
Requesting the time
TCP: connection triggers a response
UDP: client datagram triggers a response
Example code: UDPtime.c
Available as TCP and UDP services at port 7
Test connectivity
debug protocols
find routing problems
Server sends back to client all the data it
receives from the client
Example code:
TCPecho.c and UDPecho.c