* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Download Slides
Survey
Document related concepts
Transcript
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 ?