Pipes and Socket Programming) Inter-Process Communication (IPC

Pipes and Socket Programming) Inter-Process Communication (IPC

Inter-Process Communication (IPC) • Data exchange techniques between Systems Programming III processes: (Pipes and Socket Programming) – Message passing: files, pipes, sockets – Shared-memory model Iqbal Mohomed CSC 209 – Summer 2004 Week 8 Some Limitations Pipes and File • Limitations of files for inter-process data • A fork’d child inherits file descriptors from its exchange: parent –Slow! • Its possible to alter these using fclose() and • Limitations of pipes: fopen(): fclose(stdin); – two processes must be running on the same machine FILE* fp = fopen(“/tmp/junk”, “r”); – two processes communicating must be “related” • One could exchange two entries in the fd table by • Sockets overcome these limitations and are widely closing and reopening both streams, but there’s a used in Internet software more efficient way, using dup() or dup2() dup() and dup2() pipe() newFD = dup( oldFD); • The pipe() system call creates an internal system if (newFD < 0) {perror(“dup”);exit(1);} buffer and two file descriptors: one for reading • Or, to force the newFD to have a specific number: and one for writing returnCode = dup2(oldFD, newFD); • With a pipe, typically want the stdout of one if (returnCode < 0) {perror(“dup”);exit(1);} process to be connected to stdin of another process • In both cases, oldFD and newFD now refer to the same file … this is where dup2() becomes useful! • For dup2, if newFD is open, it is first automatically closed • Usage: • Note that dup() and dup2() refer to FDs and not streams int fd[2]; • A useful system call to convert a stream to a FD is: pipe(fd); /* fd[0] for reading; fd[1] for writing */ int fileno( FILE*fp); • Getting a stream from an FD: FILE* fdopen(int filedes,const char* mode); 1 werewolf:~/iqtesty% cat file1 Hello, my name is pipe()/dup2() example Iqbal. Output Hello, /* Equivalent to "sort < file1 | uniq*/ my #include<stdio.h> name int main() is { Marc. int fd[2]; werewolf:~/iqtesty% sort<file1 FILE *fp = fopen("file1","r"); Hello, dup2(fileno(fp), fileno(stdin)); Hello, fclose(fp); Iqbal. pipe(fd); Marc. if (fork() == 0) is { is my dup2(fd[1],fileno(stdout)); my close(fd[0]);close(fd[1]); name execl("/bin/sort","sort",(char*) 0);exit(2); name }else{ werewolf:~/iqtesty% sort < file1|uniq OR werewolf:~/iqtesty% ./a.out dup2(fd[0],fileno(stdin)); Hello, close(fd[0]);close(fd[1]); Iqbal. execl("/usr/bin/uniq","uniq",(char*)0);exit(3); Marc. } is return 0; my } name popen() and pclose() What are sockets? • popen() simplifies the sequence of: • Sockets are an extension of pipes, with the – Generating a pipe advantages that processes don’t need to be – Forking a child process related, or even on the same machine – Duplicating file descriptors – Passing command execution via an exec() • A socket is like the end point of a pipe – in • Usage: fact, the UNIX kernel implements pipes as a FILE* popen(const char* command, const char* type); pair of sockets • Example: • Two (or more) sockets must be connected FILE* pipeFP; pipeFP = popen(“/usr/bin/ls *.c”,”r”); before they can be used to transfer data • Warning: popen() can return NULL too! More on Sockets Connection-Oriented Paradigm • Two main categories of socket types: SERVER CLIENT 1. Create a socket 1. Create a socket – The UNIX domain: both processes on same socket() socket() machine 2. Assign a name to the socket – The INET domain: processes on different bind() machines 3. Establish a queue for connections • Three main types of sockets: listen() SOCK_STREAM, SOCK_DGRAM, and 4. Extract connection from queue 2. Initiate a connection accept() Established! connect() SOCK_RAW … we’ll focus on 5. Communicate! 3. Communicate! SOCK_STREAM read() read() write() write() 2 Creating the Socket Bind to a name (Server Side) int socket(int family, int type, int protocol); int bind(int sockfd, const struct sockaddr • Family specifies the protocol family: *servaddr, socklen_t addrlen); – PF_INET – IPv4 • sockfd – returned by socket – PF_LOCAL – UNIX Domain • INET Address • Type: struct sockaddr_in{ short sin_family; /*PF_INET*/ – SOCK_STREAM, SOCK_DGRAM, SOCK_RAW u_short sin_port; • Protocol: struct in_addr sin_addr; – Set to 0 except for RAW sockets char sin_zero[8]; } • Returns a socket descriptor • sin_addr can be set to INADDR_ANY to communicate with any host Set up queue (Server Side) Establish the connection (Server Side) int listen (int sockfd, int backlog) int accept(int sockfd, struct sockaddr* cliaddr, socklen_t * addrlen); • After calling listen, a socket is ready to accept • Blocks waiting for a connection (from the queue) connections • Returns a new descriptor which refers to the TCP • Prepares a queue in the kernel where partially connection with the client completed connections wait to be accepted • sockfd is the listening socket • backlog is the maximum number of partially • cliaddr is the address of the client completed connections that the kernel should • Reads and writes on the connection will use the queue socket returned by accept Establish the connection (Client Side) INET vs UNIX Domain int connect(int sockfd, const struct sockaddr • The main difference is the bind()/connect command … in the UNIX *servaddr, socklen_t addrlen); domain, the socket name is a filename, but in the INET domain, the socket name is a machine name and port number: • The kernel will choose a dynamic port and static struct sockaddr_in serv_adr; memset(&serv_adr, 0, sizeof (serv_adr)); source IP address serv_adr.sin_family = AF_INET; serv_adr.sin_addr.s_addr = htonl(INADDR_ANY); serv_adr.sin_port = htons(6789); • Returns 0 on success and –1 on failure, VERSUS #define NAME “my_sock” setting errno static struct sockaddr_un serv_adr; serv_adr.sun_family = AF_UNIX; strcpy(serv_adr.sun_path,NAME); • AF_INET/PF_INET versus AF_UNIX/PF_UNIX • Client needs to know the machine name and port of the server: struct hostent *host; host = gethostbyname(“werewolf.cdf”); 3 Network byte order Port Numbers • Intel CPUs are usually little-endian, and Sun Sparc • Well-known ports: 0 – 1023 CPUs are big-endian – 80: web • To communicate between machines with unknown or different “endian-ness” we convert numbers to – 22: ssh network byte order (big-endian) before we send – 23: telnet them. – 21: ftp • There are functions provided to do this: – unsigned long htonl(unsigned long) • Registered ports: 1024 – 49151 – unsigned short htons(unsigned short) • Private ports: 49152 - 65535 – unsigned long ntohl(unsigned long) – unsigned short ntohs(unsigned short) 4.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    4 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us