Communications (January 10)
Download
Report
Transcript Communications (January 10)
Communication
References
The 402 web site has many links to socket
tutorials.
Chapter 2.1 of the Tanenbaum, van Steen
textbook
Chapter 15, of the Steven’s book on TCP/IP
Layered Protocols
All communication is based on exchanging
messages.
Protocols control the sending and receiving
of messages
e.g.,
TCP, IP, HTTP,FTP
Layered Protocols
Many different protocols are needed at a variety of
levels e.g.,
How many volts needed for a 0 bit and for a 1 bit
How does the receiver know which is the last bit of the
message?
How is a lost message detected?
ISO developed the OSI model.
Very useful as a reference point
Internet protocols such as TCP, IP are mostly used.
Layered Protocols
2-1
Layers, interfaces, and protocols in the OSI model.
Physical Layer
The physical layer is concerned with the
transmission of 0’s and 1’s.
How many volts to use for 0 and 1
How many bits per second can be sent
Many physical layer standards have been
developed for different media e.g.,
RS-232-C standard for serial communication
lines
Data Link Layer
The physical layer just sends bits.
A mechanism is needed to detect and correct
errors such as damaged or lost messages
The data link layer groups bits into units
(frames). Each frame has
Sequence numbers for detecting lost messages
Checksums for detecting damage
Network Layer
For a message to get from the sender to
the receiver, it may need to make a number
of hops (in a wide-area network)
There is usually more than one path.
Choosing a path is called routing
Most widely used network protocol is the
connectionless IP (Internet Protocol)
Transport Protocols
The transport layer turns the underlying
network into something that an application
developer can use.
Upon receiving a message from the
application layer, the transport layer
breaks it into small pieces enough for
transmission, assigns each one a sequence
number and then sends them all.
Transport Protocols
At the receiving end, the transport layer has to
put back together the pieces into the message
before passing it to the application.
The Internet transport protocol is called
Transmission Control Protocol (TCP).
TCP is a reliable transport protocol i.e., it can deal with
losses
The Internet transport protocol that does not
deal with losses is called UDP.
The official ISO transport protocol has 5 variants
The Internet does not have protocols higher than
TCP/UDP except for application layer protocols
such as nntp, ftp, http.
Client-Server Paradigm
Many network applications use a form of
communication known as the client-server
paradigm
Server application waits (passively) for contact.
Client initiates the contact.
Client and server applications interact directly
with a transport-layer protocol for establishing
communication and to send and receive
information.
The transport layer uses lower layer protocols to
send and receive individual messages.
Application Programming
Interface: API
The interface an application uses when it interacts
with the transport protocol software is known as
an Application Programming Interface (API).
An API defines a set of operations that an
application can perform when it interacts with a
protocol.
APIs are defined as follows:
Provide a set of procedures that can be called
For each procedure, define the arguments expected
Usually there is a procedure for each basic operation
e.g., send, receive
Socket API
Introduced in 1981
Originally only Unix
Implemented as a library
This can be used to communicate with TCP
or UDP
Socket Programming using TCP
Socket: a door between application process and endend-transport protocol (UDP or TCP)
TCP service: reliable transfer of bytes from one
process to another
UDP service: does not guarantee a reliable transfer
of bytes
controlled by
application
developer
controlled by
operating
system
process
process
socket
TCP with
buffers,
variables
host or
server
internet
socket
TCP with
buffers,
variables
host or
server
controlled by
application
developer
controlled by
operating
system
Unix File I/O
How is a socket implemented?
To understand this, let us look at file I/O.
A file descriptor is a small, positive integer.
int fd;
char buf[256];
fd = open(“a.txt”, O_RDWR);
write(fd, buf, sizeof(buf));
close(fd)
The file descriptor is used to refer to the file
a.txt
Unix Descriptor Table
Each process has a descriptor table
Each socket has an entry in the descriptor table
Descriptor Table
0
Data structure for file 0
1
2
Data structure for file 1
3
4
Data structure for socket
Socket Descriptor Data
Structure
Descriptor Table
0
1
2
3
4
Family: AF_INET
Service: SOCK_STREAM
Local IP: 158.108.33.66
Remote IP: 158.108.2.71
Local Port: 2249
Remote Port: 21
Sockets and Descriptors
In Unix sockets are integrated with I/O.
The OS provides a single set of
descriptors for files, devices,
communication.
Read and Write can be used for both files
and communication
However, socket programming does differ
from file I/O in that there are many
details needed to use a socket e.g.,
transport protocol, address of the remote
machine, etc
Sockets and Descriptors
Before an application can communicate, it must
request that the operating system create a socket
to be used for communication.
The system returns a small integer descriptor
that identifies the socket.
The application uses the descriptor as an
argument in a procedure of the API that is
defined for communication.
Socket Creation
descriptor = socket(domain, type, protocol)
domain specifies the specifies the addressing format to
be used by the socket. AF_INET specifies Internet
address and AF_UNIX specifies file path names.
type specifies the type of communication the socket will
use.
• SOCK_STREAM: connection-oriented stream transfer
• SOCK_DGRAM: connectionless message-oriented transfer
protocol specifies a particular transport protocol; usually
0 = default for type
A –1 is returned if an error occurs.
Socket Creation
Transport Protocols
TCP -- connection-oriented
UDP -- connectionless
It is possible to have more than one
transport protocol for a specific type of
communication.
Socket Creation
Example
#include <sys/types.h>
#include <sys/socket.h>
if ((s = socket(AF_INET, SOCK_STREAM, 0) ) < 0){
perror(“socket”);}
Endpoint Addresses
A socket association is characterized as
follows:
communication protocol, local address, local
port, remote address, remote port
Local address, port are defined using the
bind call
Remote address, port are defined using
connect, sendto
Address Representation
This structure holds socket address information for many
types of sockets.
struct sockaddr {
unsigned short sa_family; // address family,
char sa_data[14]; // 14 bytes of protocol address };
sa_family represents the address format i.e., AF_INET.
sa_data contains an address and port number for the socket.
This structure is considered “unyieldy” since most
programmers do not want to pack sa_data by hand.
Programmers deal with the sockaddr_in structure
Address Representation
Internally an address is represented as a 32-bit
integer
struct in_addr {
u_long s_addr;
}
struct sockaddr_in {
short sin_family;
u_short sin_port
struct in_addr sin_addr
char sin_zero[8];
}
/*Address Family*/
/*port number*/
/* network address*/
/*unused*/
Address Representation
sin_family represents the address format
sin_port specifies a port number which is
associated with a process.
sin_addr specifies the address of a host
machine
sin_zero is used to fill out the structure.
Address Representation
sockaddr_in is used for TCP (connection-
oriented) and sockaddr_un is used for UDP
(connectionless)
The API procedures assume that a variable
that is a pointer to sockaddr is used.
The programmer should cast a variable of
type sockaddr_in (or sockaddr_out) to a
variable that is a pointer to sockaddr
Data Representation
Integers are not represented the same on all machine
architectures
little endian: least significant byte first; the Intel series,
VAX
big endian: most significant byte first (this is network byte
order); IBM 370, Motorola 68000 and Sun Sparc
When little endian computers are going to pass
integers over the network (e.g., IP addresses), they
need to convert them to network byte order.
Data Representation
m = ntohl(m): network to host byte order (32 bit)
m = htonl(m): host to network byte order (32 bit)
m = ntohs(m): network to host byte order (16 bit)
m = htons(m): host to network byte order (16 bit)
Address Conversion
host name to IP address: gethostbyname()
IP address to name: gethostbyaddr()
bind ()
bind(int socket, struct sockaddr *localaddr, int
addrlen)
localaddr is a structure that specifies the local
address to be assigned to the socket.
addrlen specifies the length of the sockaddr
structure pointed to by the address argument.
Used by both TCP and UDP.
bind()
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int s;
struct sockaddr_in sin;
if ((s = socket(AF_INET, SOCK_STREAM,0)) < 0 {
/*error*/};
memset((char *) &sin, 0, sizeof(sin));
sin.sin_family = AF_INET:
sin.sin_port = htons(6000);
sin.sin_addr.s_addr = htonl(INADDR_ANY);
if bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0)
{…}
connect()
Client contacts server by
Creating client-local TCP socket
Specifying IP address, port number of server process
Calling the connect() system call
connect()
int connect(int s, struct sockaddr *name, int namelen)
client
issues connect() to establish remote
address and port (stream, datagram sockets)
Establish connection (stream socket)
The call fails if the host is not listening to port.
send()
int send(int socket, const void *msg, int len, int
flags);
msg specifies a pointer to the first of the data to be
sent
len is an integer that specifies the amount of data to be
sent
flags are used to specify special options which are mostly
intended for system debugging (don’t worry about this;
just set it to 0)
Used for stream communications
recv()
int recv(int socket, void *msg, int len, int flags);
Similar to send() except this is used to
receive data and put into msg
listen()
Client must contact server
For a client to contact a server, the server process must
first be running
The server must have created a socket that is used to
welcome the client’s contact
The server must be “listening” for the client’s contact by
using the listen() system call.
listen()
int listen(int s, int queuesize)
queuesize
specifies a length for the socket’s
request queue.
The OS builds a separate request queue for
each socket.
Client requests are put into the queue.
Socket being listened to can’t be used for
client.
accept()
When contacted by client, server TCP creates a
new socket for the server process to communicate
with the client
Allows server to talk with multiple clients
accept()
int accept (int s, struct sockaddr *addr, int
*addrlen);
All servers begin by calling socket to create socket and
bind to specify a protocol port number.
These two calls are sufficient for a server to start
accepting messages in a connectionless transport.
An extra call ( accept() ) is needed for a connectionoriented protocol.
accept() fills in fields of argument addr with the
address of the client that formed the connection and
sets addrlen to the length of the address.
accept()
The server uses the new socket to communicate
with the client and then closes the socket when
finished.
The original socket remains unchanged and this
is used to accept the next connection from a
client.
Getting IP address/port from
socket
int getsockname(int sockfd, struct sockaddr
*localaddr, socklen_t *addrlen)
Get the local IP/port bound to socket
int getpeername(int sockfd, struct sockaddr
*remoteaddr, socklen_t *addrlen)
Get the IP/port of remote endpoint
Two other useful functions
struct hostent *gethostbyaddr (void *addr, size_t len,
int type);
Converts from IP address to domain name
struct hostent *gethostbyname (char *name);
Converts from domain name to IP address
struct hostent {
char
*h_name;/* official name of host */
char
**h_aliases;
/* alias list */
int
h_addrtype;
/* address type */
int
h_length;
/* address length*/
char
**h_addr_list; /* address list */
}
macro h_addr is defined to be h_addr_list[0]
Sequence of Socket System
Calls
Client
Server
socket
socket
bind
listen
connect
Connection
request
accept
send
receive
receive
send
close
EOF
close
Example (Stream Socket;
setting address)
setaddr(sp, host, port)
struct sockaddr_in *sp;
char *host;
int port;
{
struct hostent *hp;
hp = gethostbyname(host);
struct hostent {
char *h_name;/* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* address type */
int h_length;
/* address length*/
char **h_addr_list; /* address list */
}
Example (Stream Socket;
setting address)
if (hp == NULL) {
fprintf(stderr, "%s: unknown host\n", host);
exit(1);
}
sp->sin_family = AF_INET;
bcopy(hp->h_addr, &sp->sin_addr, hp->h_length);
sp->sin_port = htons(port);
}
struct in_addr {
u_long s_addr;
}
struct sockaddr_in {
short sin_family;
/*Address Family*/
u_short sin_port
/*port number*/
struct in_addr sin_addr /* network address*/
char sin_zero[8];
/*unused*/
}
Example (Stream Socket;
socket creation)
streamsocket(port)
int port;
{
int s;
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
s = socket(AF_INET, SOCK_STREAM, 0);
Example (Stream Socket;
socket creation)
if (s < 0)
error("socket");
if (bind(s, (struct sockadd_in *) &sin, sizeof (sin)) <
0)
error("bind");
return s;
}
Example (Stream Socket;
socket creation)
/*
* System call failed: print a message and give up.
*/
error(msg)
char *msg;
{
extern char *myname;
/* program name */
fprintf(stderr, "%s: ", myname);
perror(msg);
exit(1);
}
Example (Stream Socket;
client)
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
char *myname;
Example (Stream Socket;
client)
main(argc, argv)
char *argv[];
{
struct sockaddr_in sin;
int s, n, zero;
char buf[BUFSIZ];
myname = argv[0];
if (argc < 2) {
fprintf(stderr, "usage: %s port [host]\n",
myname);
exit(1);
}
Example (Stream Socket;
client)
s = streamsocket(0); /* port 0 means "any port" */
setaddr(&sin, argc > 2 ? argv[2] : "localhost",
atoi(argv[1]));
/* connect a socket using name specified by the command
line */
if (connect(s, (struct sockaddr_in *) &sin,
sizeof(sin)) < 0) {
error("connecting stream socket");
exit(1);
}
Example (Stream Socket;
client)
printf("Type in text\n");
/* read text from the standard input */
while ((n = read(0, buf, sizeof(buf))) > 0){
/* send the text through socket */
if (write(s, buf, sizeof(buf)) < 0)
error("writing on stream socket");
bzero(buf, sizeof(buf));
}
close(s);
exit(0);
}
Example (Stream Socket;
server)
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
char *myname;
#define MSGSIZE 1
Example (Stream Socket;
server)
main(argc, argv)
char *argv[];
{
struct sockaddr_in from;
int s, n, fromlen, msgs, rval;
struct hostent *hp;
char
buf[BUFSIZ];
myname = argv[0];
Example (Stream Socket;
server)
if (argc < 2) {
fprintf(stderr, "usage: %s port\n", argv[0]);
exit(1);
}
s = streamsocket(atoi(argv[1]));
fromlen = sizeof(from);
if (getsockname(s, &from, &fromlen)) {
error("getting socket name");
exit(1);
}
printf("Socket has port #
%d\n",ntohs(from.sin_port));
listen(s, 5);
Example (Stream Socket;
server)
for (;;) {
/*start accepting connections*/
msgs = accept(s, 0, 0);
if (msgs == -1)
error("accept");
else do {
bzero(buf, sizeof(buf));
Example (Stream Socket;
server)
if ((rval = read(msgs, buf, sizeof(buf))) < 0)
error("reading stream message");
if (rval == 0)
printf("Ending connection\n");
else {
printf("%s\n",buf);
}
UDP: User Datagram Protocol [RFC
768]
“no frills,” “bare bones” Internet transport
protocol
“best effort” service, UDP segments may be:
lost
delivered out of order to app
connectionless:
no handshaking between UDP sender, receiver
each UDP segment handled independently of
others
Why use UDP instead of TCP
No connection establishment (which can add delay)
Remember that TCP does a three-way handshake before
transmitting data. UDP does not.
TCP maintains connection state
Receive and send buffers
Sequence and acknowledgement numbers
Congestion control parameters
Smaller segment overhead
Each TCP segment has 20 bytes of header overhead while
each UDP segment has 8 bytes.
The overhead in TCP includes sequence and acknowledgement
numbers, and a flow congestion field.
There is no congestion control
UDP can blast away as fast as possible
UDP
Often used for streaming multimedia apps
loss
tolerant
rate sensitive
Other UDP uses (why?):
DNS
ping
command
Applications using UDP and TCP
Email – TCP
telnet – TCP
HTTP – TCP
ftp – TCP
Remote file server (NFS) – typically UDP
DNS – typically UDP
Streaming multimedia – typically UDP
Internet telephony – typically UDP
Network management (SNMP) – typically UDP
UDP and Reliability
Lack of congestion control
It is possible to have reliable data transfer
in UDP.
The application must have acknowledgements
and retransmission mechanisms
Streaming applications do this.
API for UDP
socket() call uses SOCK_DGRAM instead of
SOCK_STREAM
There is no connect() call
Uses recvfrom() and sendto() instead of
read() and write()
There are no listen() or accept() calls
sendto()
int sendto (int socket, char *msg, int len, int
flags, struct sockaddr *to, int tolen);
to specifies the destination address and tolen
specifies the length of the destination address.
Used for datagram communications
recvfrom()
int recvfrom (int socket, char *msg, int len, int
flags, struct sockaddr *from, int fromlen);
sets from to source address of data
sets fromlen to valid length of from
returns number of bytes received
Other Functions
There are other functions used in
TCP/UDP that can be used to provide for
timeouts,etc;
We will discuss the use of the select()
function.
select()
int select(int maxfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
FD_CLR(int fd, fd_set *fds);
FD_ISSET(int fd, fd_set *fds);
FD_SET(int fd, fd_set *fds);
FD_ZERO(fd_set *fds);
/*
/*
/*
/*
clear the bit for fd in fds */
is the bit for fd in fds */
turn on the bit for fd in fds */
clear all bits in fds */
maxfds: number of descriptors to be tested
descriptors (0, 1, ... maxfds-1) will be tested
readfds: a set of fds we want to check if data is available
returns a set of fds ready to read
if input argument is NULL, not interested in that condition
writefds: returns a set of fds ready to write
exceptfds: returns a set of fds with exception conditions
select()
int select(int maxfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
struct timeval {
long tv_sec;
long tv_usec;
}
/* seconds /
/* microseconds */
timeout
if NULL, wait forever and return only when one of the descriptors
is ready for I/O
otherwise, wait up to a fixed amount of time specified by timeout
• if we don’t want to wait at all, create a timeout structure with timer
value equal to 0
select()
A select statement can be used to implement
….
timeouts
s = streamsocket(0);
/* port 0 means "any port" */
setaddr(&sin, argc > 2 ? argv[2] : "localhost",
atoi(argv[1]));
/* connect a socket using name specified by the command
line */
if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0)
{
error("connecting stream socket");
exit(1);
}
buf = (char *) malloc(BUFSIZ*sizeof(char));
sprintf(buf, "%d", AREYOUUP);
write(s,buf,sizeof(buf));
select()
tv.tv_sec = 20;
tv.tv_usec = 5000;
FD_CLR(s,&readfds);
FD_ZERO(&readfds);
FD_SET(s,&readfds);
while (select(s,&readfds,NULL,NULL,&tv) < 0) { };
if (FD_ISSET(s,&readfds)){
printf("Data Arrived\n");
recv(s,buf,sizeof(buf),0);
printf("buffer is %s\n",buf);
}
else
printf("timed out\n");
close(s);
exit(0);
}
Summary
This section briefly summarizes the basic
message passing primitives that can be
used by processes in a distributed
application.