Transcript Slides

An Introductory 4.4BSD
Interprocess
Communication Tutorial
Stuart Sechrest
The Socket Interface
 Funded by ARPA (Advanced Research
Projects Agency) in 1980.
 Developed at UC Berkeley
 Objective: to transport TCP/IP software to
UNIX
 The socket interface has become a standard.
History of Sockets
 Sockets were introduced in 1981 as the Unix
BSD 4.2 generic interface for Unix to Unix
communications over networks (IPC between
machines).
 In 1985, SunOS introduced NFS and RPC
over sockets.
 In 1986, AT&T introduced the Transport Layer
Interface (TLI) with socket-like functionality but
more network independent.
 Another popular socket Interface Winsock
Berkeley Unix 4.4BSD IPC choices.
 PIPES a one-way mechanism that allows two
related processes ( one could be an ancestor
of the other) to send a byte stream from one
to the other.
 Sockets software entity that connects an
application to a network protocol.
 Socketpairs a pair of connected sockets for
two-way stream communication.
Concepts
 A program is both a sequence of statements
and a rough way of referring to the
computation that occurs when the compiled
statements are run.
 A process is an instance of a program
running in a computer
 Forking is when a program control splits into
two independent lines.
Fork() system call.
 fork()
This system call causes the current process to
be split into two processes - a parent process,
and a child process.
 In the parent process. the return value is the
process ID (PID) of the child process.
 Inside the child process the return value is '0'.
 In case of failure (not enough memory, too
many processes, etc.), no new process is
created, and the return value of the call is '-1'.
Pipes.
 A pipe is a one-way communication
mechanism, with one end opened for reading
and the other end for writing.
 pipe() system call is used to create a readwrite pipe that may later be used to
communicate with a forked off process.
 An array of 2 integers as the argument that
will be used to save the two file descriptors
used to access the pipe.
 first to read from the pipe
 second to write to the pipe.
Use of a pipe
#include <stdio.h>
#define DATA “PIPE example"
main()
{
int sockets[2], child;
/* Create a pipe */
if (pipe(sockets) < 0) {
perror("opening stream socket pair");
exit(10);
}
if ((child = fork()) == -1)
perror("fork");
Use of pipe (continued)
else if (child) {
char buf[1024];
/* This is still the parent. It reads the child’s message. */
close(sockets[1]);
if (read(sockets[0], buf, 1024) < 0)
perror("reading message");
printf("-->%s\n", buf);
close(sockets[0]);
} else {
/* This is the child. It writes a message to its parent. */
close(sockets[0]);
if (write(sockets[1], DATA, sizeof(DATA)) < 0)
perror("writing message");
close(sockets[1]);
}
}
Effect of a fork.
Socketpairs
 Socketpair a pair of connected sockets for
two-way stream communication.
 socketpair(int d, int type, int protocol, int sv[2])
 The call creates an unnamed pair of
connected sockets in the specified domain d,
of the specified type, and using the optionally
specified protocol. The descriptors used in
referencing the new sockets are returned in
sv[0] and sv[1].
 It returns 0 on success and -1 otherwise
Use of a socket pair
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#define DATA1 “First message . . ."
#define DATA2 “Second message . . ."
main()
{
int sockets[2], child;
char buf[1024];
if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
perror("opening stream socket pair");
exit(1);
}
Use of a socket pair (continued)
if ((child = fork()) == -1)
perror("fork");
else if (child) { /* This is the parent. */
close(sockets[0]);
if (read(sockets[1], buf, 1024, 0) < 0)
perror("reading stream message");
printf("-->%s\n", buf);
if (write(sockets[1], DATA2, sizeof(DATA2)) < 0)
perror("writing stream message");
close(sockets[1]);
} else { /* This is the child. */
close(sockets[1]);
if (write(sockets[0], DATA1, sizeof(DATA1)) < 0)
perror("writing stream message");
if (read(sockets[0], buf, 1024, 0) < 0)
perror("reading stream message");
printf("-->%s\n", buf);
close(sockets[0]);
}}
Effect of the fork
Sockets
 The idea of sockets is that there is a server that is
listening on a particular port at a particular address.
 A client tries to open a connection with the server.
Considering that everything is in order (no errors), the
server accepts the connection and thus creates a
socket.
Sockets
 Once the socket is created, communication between
the two computers can take place.
 There are several different ways a connection can be
established.

Examples
 TCP / UDP (Connection vs. Connectionless)
 IP / IPX
Modes of services available.
Connection-oriented and connectionless
 Connection-oriented service an application
program must first establish a connection to the
other end before the actual communication can
take place.(reliable delivery service)
 Connectionless mode the application sends its
data immediately without waiting for the
connection to get established.
Socket Calls for connection-oriented
communication
Socket calls for Connectionless
communication
Socket Functions
 socket: create a descriptor for use in network communication.
int socket(int family, int type, int protocol)
 connect: connect to a remote peer (used by client)
int connect(int sockfd, struct sockaddr *addr, int addrlen);
 bind: bind a local IP address and protocol number to a socket.
int bind(int sockfd, string addr [, int port])
 listen: place the socket in passive mode and set the number of
incoming TCP connections the system will enqueue.
int listen(int s, int backlog);
 accept: accept the next incoming connection (by server).
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
Socket Functions (Continued)
 close: terminate communication and
deallocate a descriptor.
 write: send outgoing data across a
connection.
int write(int sockfd, void *buf, int count);
 read: acquire incoming data from a
connection.
int read(int sockfd, void *buf, int count);
Creating A Socket
 The socket system call establishes the end point of a
communications link.
sd=socket(family, type, protocol);
family = AF_UNIX, AF_INET, PF_INET or AF_IMPLINK
type = SOCK_STREAM, SOCK_DGRAM or SOCK_RAW
protocol = IPPROTO_TCP _UDP _ICMP or _RAW
 The socket descriptor sd is then used in system calls.
 Close sockets with close()
Domain
 Domain is the space from which an address
is drawn.
 There are several Domains for sockets. For
the purpose of this presentation the internet
domain AF_INET will be used in the code
Examples.
 Addresses in the Internet domain consist of a
machine network address and a port.
Type of Communication
 SOCK_STREAM provides a data delivery
service as a sequence of bytes and does not
preserve message boundaries.
 SOCK_DGRAM provides a data delivery
service in blocks of bytes called datagrams or
packet.
 A datagram is an independent, self-contained
message sent over the network whose
arrival, arrival time, and content are not
guaranteed.
Data Conversion Functions
 The functions htons, ntohs, htonl, and ntohl
are used to convert binary integers between
the host’s native byte order and the network
standard byte order.
 This makes the source code portable to any
machine, independent of the the native byte
order
Code Examples
Internet Domain Datagrams
Reading Internet domain datagrams
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
/*
* In the included file <netinet/in.h> a sockaddr_in is defined as follows:
* struct sockaddr_in {
* short sin_family;
* u_short sin_port;
* struct in_addr sin_addr;
* char sin_zero[8];
* };
*
* This program creates a datagram socket, binds a name to it, then
reads from the socket. */
Reading Internet domain datagrams
main()
{
int sock, length;
struct sockaddr_in name;
char buf[1024];
/* Create socket from which to read. */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("opening datagram socket");
exit(1);
}
/* Create name with wildcards. */
name.sin_family = AF_INET;
name.sin_addr.s_addr = INADDR_ANY;
name.sin_port = 0;
if (bind(sock, &name, sizeof(name))) {
perror("binding datagram socket");
exit(1);
}
Reading Internet domain datagrams
/* Find assigned port value and print it out. */
length = sizeof(name);
if (getsockname(sock, &name, &length)) {
perror("getting socket name");
exit(1);
}
printf("Socket has port #%d\n", ntohs(name.sin_port));
/* Read from the socket */
if (read(sock, buf, 1024) < 0)
perror("receiving datagram packet");
printf("-->%s\n", buf);
close(sock);
}
Sending Internet domain datagrams
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define DATA “DATAGRAM example . . ."
/*
* Here I send a datagram to a receiver whose name I get from the
command
* line arguments. The form of the command line is dgramsend hostname
* portnumber
*/
main(argc, argv)
int argc;
char *argv[];
{
int sock;
struct sockaddr_in name;
struct hostent *hp, *gethostbyname();
Sending Internet domain datagrams
/* Create socket on which to send. */
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("opening datagram socket");
exit(1);
}
/*
* Construct name, with no wildcards, of the socket to send to.
* Getnostbyname() returns a structure including the network address
* of the specified host. The port number is taken from the command
* line.
*/
hp = gethostbyname(argv[1]);
if (hp == 0) {
fprintf(stderr, "%s: unknown host0, argv[1]);
exit(2);
}
Sending Internet domain datagrams
bcopy(hp->h_addr, &name.sin_addr, hp->h_length);
name.sin_family = AF_INET;
name.sin_port = htons(atoi(argv[2]));
/* Send message. */
if (sendto(sock, DATA, sizeof(DATA), 0, &name, sizeof(name)) < 0)
perror("sending datagram message");
close(sock);
}
Code Examples
Internet Domain stream connection
Passive/Active Socket
 A passive socket is used by a server to wait
for an incoming connection.
 An active socket is used by a client to initiate
a connection.
Client Internet Domain Stream
Connection
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define DATA "Half a league, half a league . . ."
/*
This program creates a socket and initiates a connection with the socket
given in the command line. One message is sent over the connection and then
the socket is closed, ending the connection. The form of the command line is
streamwrite hostname portnumber
*/
main(argc, argv)
int argc;
char *argv[];
{
Client Internet Domain Stream
Connection
int sock;
struct sockaddr_in server;
struct hostent *hp, *gethostbyname();
char buf[1024];
/* Create socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
/* Connect socket using name specified by command line. */
server.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
if (hp == 0) {
fprintf(stderr, "%s: unknown host0, argv[1]);
exit(2);
}
Client Internet Domain Stream
Connection
bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
server.sin_port = htons(atoi(argv[2]));
if (connect(sock, &server, sizeof(server)) < 0) {
perror("connecting stream socket");
exit(1);
}
if (write(sock, DATA, sizeof(DATA)) < 0)
perror("writing on stream socket");
close(sock);
}
Server Internet Domain Stream
Connection
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#define TRUE 1
/*This program creates a socket and then begins an infinite loop. Each time
through the loop it accepts a connection and prints out messages from it.
When the connection breaks, or a termination message comes through, the
program accepts a new connection. */
main()
{
int sock, length;
struct sockaddr_in server;
int msgsock;
char buf[1024];
int rval;
int i;
Server Internet Domain Stream
Connection
/* Create socket */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("opening stream socket");
exit(1);
}
/* Name socket using wildcards */
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = 0;
if (bind(sock, &server, sizeof(server))) {
perror("binding stream socket");
exit(1); }
/* Find out assigned port number and print it out */
length = sizeof(server);
if (getsockname(sock, &server, &length)) {
perror("getting socket name");
exit(1); }
Server Internet Domain Stream
Connection
printf("Socket has port #%d\n", ntohs(server.sin_port));
/* Start accepting connections */
listen(sock, 5);
do {
msgsock = accept(sock, 0, 0);
if (msgsock == -1)
perror("accept");
else do {
bzero(buf, sizeof(buf));
if ((rval = read(msgsock, buf, 1024)) < 0)
perror("reading stream message");
i = 0;
if (rval == 0)
printf("Ending connection\n");
else
printf("-->%s\n", buf);
} while (rval != 0);
close(msgsock);
} while (TRUE); }
Any Questions ?