Systems Programming III (Pipes and Socket Programming) : Iqbal Mohomed CSC 209 - Summer 2004 Week 8
Systems Programming III (Pipes and Socket Programming) : Iqbal Mohomed CSC 209 - Summer 2004 Week 8
Systems Programming III (Pipes and Socket Programming) : Iqbal Mohomed CSC 209 - Summer 2004 Week 8
Some Limitations
Limitations of files for inter-process data exchange:
Slow!
Limitations of pipes:
two processes must be running on the same machine two processes communicating must be related
Sockets overcome these limitations and are widely used in Internet software
One could exchange two entries in the fd table by closing and reopening both streams, but theres a more efficient way, using dup() or dup2()
In both cases, oldFD and newFD now refer to the same file For dup2, if newFD is open, it is first automatically closed Note that dup() and dup2() refer to FDs and not streams A useful system call to convert a stream to a FD is:
int fileno( FILE*fp);
pipe()
The pipe() system call creates an internal system buffer and two file descriptors: one for reading and one for writing With a pipe, typically want the stdout of one process to be connected to stdin of another process this is where dup2() becomes useful! Usage:
int fd[2]; pipe(fd); /* fd[0] for reading; fd[1] for writing */
pipe()/dup2() example
/* Equivalent to "sort < file1 | uniq*/ #include<stdio.h> int main() { int fd[2]; FILE *fp = fopen("file1","r"); dup2(fileno(fp), fileno(stdin)); fclose(fp); pipe(fd); if (fork() == 0) { dup2(fd[1],fileno(stdout)); close(fd[0]);close(fd[1]); execl("/bin/sort","sort",(char*) 0);exit(2); }else{ dup2(fd[0],fileno(stdin)); close(fd[0]);close(fd[1]); execl("/usr/bin/uniq","uniq",(char*)0);exit(3); } return 0; }
werewolf:~/iqtesty% cat file1 Hello, my name is Iqbal. Hello, my name is Marc. werewolf:~/iqtesty% sort<file1 Hello, Hello, Iqbal. Marc. is is my my name name werewolf:~/iqtesty% sort < file1|uniq OR werewolf:~/iqtesty% ./a.out Hello, Iqbal. Marc. is my name
Output
Usage:
FILE* popen(const char* command, const char* type);
Example:
FILE* pipeFP; pipeFP = popen(/usr/bin/ls *.c,r);
More on Sockets
Two main categories of socket types:
The UNIX domain: both processes on same machine The INET domain: processes on different machines
Three main types of sockets: SOCK_STREAM, SOCK_DGRAM, and SOCK_RAW well focus on SOCK_STREAM
Connection-Oriented Paradigm
SERVER
1. Create a socket socket() 2. Assign a name to the socket bind() 3. Establish a queue for connections listen() 4. Extract connection from queue Established! accept() 5. Communicate! read() write()
CLIENT
1. Create a socket socket()
Type:
SOCK_STREAM, SOCK_DGRAM, SOCK_RAW
Protocol:
Set to 0 except for RAW sockets
After calling listen, a socket is ready to accept connections Prepares a queue in the kernel where partially completed connections wait to be accepted backlog is the maximum number of partially completed connections that the kernel should queue
Blocks waiting for a connection (from the queue) Returns a new descriptor which refers to the TCP connection with the client sockfd is the listening socket cliaddr is the address of the client Reads and writes on the connection will use the socket returned by accept
The kernel will choose a dynamic port and source IP address Returns 0 on success and 1 on failure, setting errno
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);
Port Numbers
Well-known ports: 0 1023
80: web 22: ssh 23: telnet 21: ftp