Preface
Environment
Cygwin Run in the Windows(Simulation of UNIX)
Resource
Cygwin Install:http://cygwin.com/install.html
Cygwin API:http://cygwin.com/cygwin-api/
Lab 1 Program Layout
Content
Ex. 2.3 P.25
Exercise 2.3
Use ls -l to compare the sizes of the executable modules for the following two C programs. Explain the results.
Version 1: largearrayinit.c
Version 2: largearray.c
Source
Version 1: largearrayinit.c
#includeint myarray[50000] = {1, 2, 3, 4}; int main(void) { myarray[0] = 3; printf("myarray[0]=%d myarray[1]=%d myarray[2]=%d myarray[3]=%d",myarray[0],myarray[1],myarray[2],myarray[3]); return 0; }
Version 2: largearray.c
#includeint myarray[50000]; int main(void) { myarray[0] = 3; printf("myarray[0]=%d myarray[1]=%d myarray[2]=%d",myarray[0],myarray[1],myarray[2]); return 0; }
Result
Version 1: largearrayinit.c
Version 2: largearray.c
Lab2 Argument array
Content
Program 2.1 and 2.2, p.34-37
Program 2.2 makeargv.c
An implementation of makeargv.
Program 2.1 argtest.c
A program that takes a single string as its command-line argument and calls makeargv to create an argument array.
Source
Program 2.2 makeargv.c
#include#include #include <string.h> int makeargv(const char *s, const char *delimiters, char ***argvp) { int error; int i; int numtokens; const char *snew; char *t; if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) { errno = EINVAL; return -1; } *argvp = NULL; snew = s + strspn(s, delimiters); /* snew is real start of string */ if ((t = malloc(strlen(snew) + 1)) == NULL) return -1; strcpy(t, snew); numtokens = 0; if (strtok(t, delimiters) != NULL) /* count the number of tokens in s */ for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ; /* create argument array for ptrs to the tokens */ if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) { error = errno; free(t); errno = error; return -1; } /* insert pointers to tokens into the argument array */ if (numtokens == 0) free(t); else { strcpy(t, snew); **argvp = strtok(t, delimiters); for (i = 1; i < numtokens; i++) *((*argvp) + i) = strtok(NULL, delimiters); } *((*argvp) + numtokens) = NULL; /* put in final NULL pointer */ return numtokens; }
Program 2.1 argtest.c
#include#include int makeargv(const char *s, const char *delimiters, char ***argvp); int main(int argc, char *argv[]) { char delim[] = " \t"; int i; char **myargv; int numtokens; if (argc != 2) { fprintf(stderr, "Usage: %s string\n", argv[0]); return 1; } if ((numtokens = makeargv(argv[1], delim, &myargv)) == -1) { fprintf(stderr, "Failed to construct an argument array for %s\n", argv[1]); return 1; } printf("The argument array contains:\n"); for (i = 0; i < numtokens; i++) printf("%d:%s\n", i, myargv[i]); return 0; }
Result
Lab3 env
Content
Example 2.22, p.49
Example 2.24, p.51
Example 2.22 environ.c
The following C program outputs the contents of its environment list and exits.
Exercise 2.24 getpaths.c
Write a function to produce an argument array containing the components of the PATH environment variable.
Source
Example 2.22 environ.c
#includeextern char **environ; int main(void) { int i; printf("The environment list follows:\n"); for(i = 0; environ[i] != NULL; i++) printf("environ[%d]: %s\n", i, environ[i]); return 0; }
Exercise 2.24 getpaths.c
#include#define PATH_DELIMITERS ":" int makeargv(const char *s, const char *delimiters, char ***argvp); char **getpaths(void) { char **myargv; char *path; path = getenv("PATH"); if (makeargv(path, PATH_DELIMITERS, &myargv) == -1) return NULL; else return myargv; }
getpathstest.c
#includechar **getpaths(void); int main(void) { char **paths; int i; paths = getpaths(); if (paths == NULL) { fprintf(stderr,"No path variable\n"); return 1; } for (i = 0; paths[i] != NULL; i++) printf("[%d]:%s\n", i, paths[i]); return 0; }
Result
Example 2.22 environ.c
Exercise 2.24 getpaths.c
Lab 4 Process Chain and Fan
Content
Program 3.1 and 3.2, p.67, 68
Program 3.1 simplechain.c
A program that creates a chain of n processes, where n is a command-line argument.
Program 3.2 simplefan.c
A program that creates a fan of n processes where n is passed as a command-line argument.
Source
Program 3.1 simplechain.c
#include#include #include int main (int argc, char *argv[]) { pid_t childpid = 0; int i, n; if (argc != 2){ /* check for valid number of command-line arguments */ fprintf(stderr, "Usage: %s processes\n", argv[0]); return 1; } n = atoi(argv[1]); for (i = 1; i < n; i++) if (childpid = fork()) break; fprintf(stderr, "i:%d process ID:%ld parent ID:%ld child ID:%ld\n", i, (long)getpid(), (long)getppid(), (long)childpid); return 0; }
Program 3.2 simplefan.c
#include#include #include int main (int argc, char *argv[]) { pid_t childpid = 0; int i, n; if (argc != 2){ /* check for valid number of command-line arguments */ fprintf(stderr, "Usage: %s processes\n", argv[0]); return 1; } n = atoi(argv[1]); for (i = 1; i < n; i++) if ((childpid = fork()) <= 0) break; fprintf(stderr, "i:%d process ID:%ld parent ID:%ld child ID:%ld\n", i, (long)getpid(), (long)getppid(), (long)childpid); return 0; }
Result
Program 3.1 simplechain.c
Program 3.2 simplefan.c
Lab 5 wait()
Content
Ex. 3.21, p.76
Exercise 3.21 chainwaitmsg.c
The following program creates a process chain. Only one forked process is a child of the original process.
Source
Exercise 3.21 chainwaitmsg.c
#include#include #include #include #include int main (int argc, char *argv[]) { pid_t childpid; int i, n; pid_t waitreturn; if (argc != 2){ /* check number of command-line arguments */ fprintf(stderr, "Usage: %s processes\n", argv[0]); return 1; } n = atoi(argv[1]); for (i = 1; i < n; i++) if (childpid = fork()) break; while(childpid != (waitreturn = wait(NULL))) if ((waitreturn == -1) && (errno != EINTR)) break; fprintf(stderr, "I am process %ld, my parent is %ld\n", (long)getpid(), (long)getppid()); return 0; }
Result
Exercise 3.21 chainwaitmsg.c
Lab 6 exec()
Content
Program 3.5, p.81
Program 3.5 execcmd.c
A program that creates a child process to execute a command. The command to be executed is passed on the command line.
Source
r_wait.c
#include#include pid_t r_wait(int *stat_loc) { int retval; while (((retval = wait(stat_loc)) == -1) && (errno == EINTR)) ; return retval; }
Program 3.5 execcmd.c
#include#include #include #include #include #include "restart.h" int main(int argc, char *argv[]) { pid_t childpid; if (argc < 2){ /* check for valid number of command-line arguments */ fprintf (stderr, "Usage: %s command arg1 arg2 ...\n", argv[0]); return 1; } childpid = fork(); if (childpid == -1) { perror("Failed to fork"); return 1; } if (childpid == 0) { /* child code */ execvp(argv[1], &argv[1]); perror("Child failed to execvp the command"); return 1; } if (childpid != r_wait(NULL)) { /* parent code */ perror("Parent failed to wait"); return 1; } return 0; }
Result
Program 3.5 execcmd.c
Lab 7*
Content
Please run the program with command line is “./argtest *.c”. Notice its output.
Source
argtest.c
#include#include int makeargv(const char *s, const char *delimiters, char ***argvp); int main(int argc, char *argv[]) { char delim[] = " \t"; int i; char **myargv; int numtokens; if (argc != 2) { fprintf(stderr, "Usage: %s string\n", argv[0]); return 1; } if ((numtokens = makeargv(argv[1], delim, &myargv)) == -1) { fprintf(stderr, "Failed to construct an argument array for %s\n", argv[1]); return 1; } printf("The argument array contains:\n"); for (i = 0; i < numtokens; i++) printf("%d:%s\n", i, myargv[i]); return 0; }
Result
argtest.c
Lab 8 Basic file operations
Content
Program 4.9, 4.2, p.106, p.98
Program 4.2 copyfile1.c
The copyfile.c function copies a file from fromfd to tofd.
Example 4.7 simplecopy.c
The following program calls copyfile to copy a file from standard input to standard output.
Source
Program 4.2 copyfile1.c
#include#include "restart.h" #define BLKSIZE 1024 int copyfile(int fromfd, int tofd) { char buf[BLKSIZE]; int bytesread, byteswritten; int totalbytes = 0; for ( ; ; ) { if ((bytesread = r_read(fromfd, buf, BLKSIZE)) <= 0) break; if ((byteswritten = r_write(tofd, buf, bytesread)) == -1) break; totalbytes += byteswritten; } return totalbytes; }
Example 4.7 simplecopy.c
#include#include int copyfile(int fromfd, int tofd); int main (void) { int numbytes; numbytes = copyfile(STDIN_FILENO, STDOUT_FILENO); fprintf(stderr, "Number of bytes copied: %d\n", numbytes); return 0; }
Result
Example 4.7 simplecopy.c
Lab 9 Inheritance of file descriptor
Content
Example 4.27
Example 4.31
Example 4.27 openfork.c
In the following program, the child inherits the file descriptor for my.dat. Each process reads and outputs one character from the file.
Example 4.31 forkopen.c
In the following program, the parent and child each open my.dat for reading, read one character, and output that character.
Source
Example 4.27 openfork.c
#include#include #include #include int main(void) { char c = '!'; int myfd; if ((myfd = open("my.dat", O_RDONLY)) == -1) { perror("Failed to open file"); return 1; } if (fork() == -1) { perror("Failed to fork"); return 1; } read(myfd, &c, 1); printf("Process %ld got %c\n", (long)getpid(), c); return 0; }
Example 4.31 forkopen.c
#include#include #include #include int main(void) { char c = '!'; int myfd; if (fork() == -1) { perror("Failed to fork"); return 1; } if ((myfd = open("my.dat", O_RDONLY)) == -1) { perror("Failed to open file"); return 1; } read(myfd, &c, 1); printf("Process %ld got %c\n", (long)getpid(), c); return 0; }
Result
Please create 1 file name “my.data” in the running time.
Example 4.27 openfork.c
Example 4.31 forkopen.c
Lab 10 Directory Access
Content
Program 5.3, P.153
Program 5.3 shownames.c
A program to list files in a directory.
Source
Program 5.3 shownames.c
#include#include #include int main(int argc, char *argv[]) { struct dirent *direntp; DIR *dirp; if (argc != 2) { fprintf(stderr, "Usage: %s directory_name\n", argv[0]); return 1; } if ((dirp = opendir(argv[1])) == NULL) { perror ("Failed to open directory"); return 1; } while ((direntp = readdir(dirp)) != NULL) printf("%s\n", direntp->d_name); while ((closedir(dirp) == -1) && (errno == EINTR)) ; return 0; }
Result
Program 5.3 shownames.c
Lab 11 file information
Content
Ex 5.9, 5.10, P.156, 157
Source
printaccessmodbad.c
#include#include #include void printaccessmodbad(char *path) { struct stat statbuf; if (stat(path, &statbuf) == -1) perror("Failed to get file status"); else printf("%s accessed: %s modified: %s", path, ctime(&statbuf.st_atime), ctime(&statbuf.st_mtime)); }
printaccessmodbadtest.c
#include#include #include void printaccessmodbad(char *path); int main(int argc, char *argv[]) { struct dirent *direntp; DIR *dirp; if (argc != 2) { fprintf(stderr,"Usage: %s directory_name\n", argv[0]); return 1; } if ((dirp = opendir(argv[1])) == NULL) { perror ("failed to open directory"); return 1; } while ( (direntp = readdir(dirp)) != NULL ) printaccessmodbad(direntp->d_name); while ( (closedir(dirp) == -1) && (errno == EINTR)) ; return 0; }
Result
printaccessmodbadtest.c
Lab 12 Traversing Directories *
Content
5.8 Exercise , P.179
Source
Isdirectory.c
#include#include #include int isdirectory(char *path) { struct stat statbuf; if (stat(path, &statbuf) == -1) return 0; else return S_ISDIR(statbuf.st_mode); }
Isdirectorytest.c
#includeint isdirectory(char *path); int main(int argc, char *argv[]) { if (argc != 2) { fprintf(stderr,"Usage: %s filename\n",argv[0]); return 1; } if (isdirectory(argv[1])) fprintf(stderr,"%s is a directory\n",argv[1]); else fprintf(stderr,"%s is not a directory\n",argv[1]); return 0; }
Result
Isdirectorytest.c(I just solve the easy question)
Lab 13 pipeline
Content
Program 6.3, p.190
Program 6.3 simpleredirect.c
A program to execute the equivalent of ls -l | sort -n +4.
Source
Program 6.3 simpleredirect.c
#include#include #include #include int main(void) { pid_t childpid; int fd[2]; if ((pipe(fd) == -1) || ((childpid = fork()) == -1)) { perror("Failed to setup pipeline"); return 1; } if (childpid == 0) { /* ls is the child */ if (dup2(fd[1], STDOUT_FILENO) == -1) perror("Failed to redirect stdout of ls"); else if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) perror("Failed to close extra pipe descriptors on ls"); else { execl("/bin/ls", "ls", "-l", NULL); perror("Failed to exec ls"); } return 1; } if (dup2(fd[0], STDIN_FILENO) == -1) /* sort is the parent */ perror("Failed to redirect stdin of sort"); else if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) perror("Failed to close extra pipe file descriptors on sort"); else { //execl("/bin/sort", "sort", "-n", "+4", NULL); execl("/bin/ls", "ls", "-l", NULL); perror("Failed to exec sort"); } return 1; }
Result
Program 6.3 simpleredirect.c
Lab 14 Block and unblock SIGINT
Content
Program 8.1, P.263
Program 8.3, P.265
Program 8.1 blocktest.c
A program that blocks and unblocks SIGINT. Now I change 10 and over.
Program 8.3 blockchild.c
A program that blocks signals before calling fork and execl.
Source
Program 8.1 blocktest.c
#include#include #include #include #include int main(int argc, char *argv[]) { int i; sigset_t intmask; int repeatfactor; double y = 0.0; if (argc != 2) { fprintf(stderr, "Usage: %s repeatfactor\n", argv[0]); return 1; } repeatfactor = atoi(argv[1]); if ((sigemptyset(&intmask) == -1) || (sigaddset(&intmask, SIGINT) == -1)){ perror("Failed to initialize the signal mask"); return 1; } for ( ; ; ) { if (sigprocmask(SIG_BLOCK, &intmask, NULL) == -1) break; fprintf(stderr, "SIGINT signal blocked\n"); for (i = 0; i < repeatfactor; i++) y += sin((double)i); fprintf(stderr, "Blocked calculation is finished, y = %f\n", y); if (sigprocmask(SIG_UNBLOCK, &intmask, NULL) == -1) break; fprintf(stderr, "SIGINT signal unblocked\n"); for (i = 0; i < repeatfactor; i++) y += sin((double)i); fprintf(stderr, "Unblocked calculation is finished, y=%f\n", y); if(i==10) break; } perror("Success to change signal mask"); return 1; }
Program 8.3 blockchild.c
#include#include #include #include #include #include #include "restart.h" int main(void) { pid_t child; sigset_t mask, omask; if ((sigfillset(&mask) == -1) || (sigprocmask(SIG_SETMASK, &mask, &omask) == -1)) { perror("Failed to block the signals"); return 1; } if ((child = fork()) == -1) { perror("Failed to fork child"); return 1; } if (child == 0) { /* child code */ execl("/bin/ls", "ls", "-l", NULL); perror("Child failed to exec"); return 1; } if (sigprocmask(SIG_SETMASK, &omask, NULL) == -1){ /* parent code */ perror("Parent failed to restore signal mask"); return 1; } if (r_wait(NULL) == -1) { perror("Parent failed to wait for child"); return 1; } return 0; }
Result
Program 8.1 blocktest.c
Program 8.3 blockchild.c
Lab 15 Catch Signal
Content
Program 8.5, P.270
Program 8.5 signalterminate.c
A program that terminates gracefully when it receives a Ctrl-C. Now I change 5 and over.
Source
Program 8.5 signalterminate.c
#include#include #include #include static volatile sig_atomic_t doneflag = 0; /* ARGSUSED */ static void setdoneflag(int signo) { doneflag = 1; } int main (void) { struct sigaction act; int count = 0; double sum = 0; double x; act.sa_handler = setdoneflag; /* set up signal handler */ act.sa_flags = 0; if ((sigemptyset(&act.sa_mask) == -1) || (sigaction(SIGINT, &act, NULL) == -1)) { perror("Failed to set SIGINT handler"); return 1; } while (!doneflag) { x = (rand() + 0.5)/(RAND_MAX + 1.0); sum += sin(x); count++; printf("Count is %d and average is %f\n", count, sum/count); if(count==5) break; } printf("Program terminating ...\n"); if (count == 0) printf("No values calculated yet\n"); else printf("Count is %d and average is %f\n", count, sum/count); return 0; }
Result
Program 8.5 signalterminate.c
Lab 16 Signal Wait
Content
Program 8.7, 8.8, P.278-279
Program 8.11, P.283
Program 8.7 simplesuspend.c
An object that allows a program to safely block on a specific signal.
Program 8.11 countsignals.c
A program that counts the number of SIGUSR1 signals sent to it.
Source
Program 8.7 simplesuspend.c
#include#include #include static int isinitialized = 0; static struct sigaction oact; static int signum = 0; static volatile sig_atomic_t sigreceived = 0; /* ARGSUSED */ static void catcher (int signo) { sigreceived = 1; } int initsuspend (int signo) { /* set up the handler for the pause */ struct sigaction act; if (isinitialized) return 0; act.sa_handler = catcher; act.sa_flags = 0; if ((sigfillset(&act.sa_mask) == -1) || (sigaction(signo, &act, &oact) == -1)) return -1; signum = signo; isinitialized = 1; return 0; } int restore(void) { if (!isinitialized) return 0; if (sigaction(signum, &oact, NULL) == -1) return -1; isinitialized = 0; return 0; } int simplesuspend(void) { sigset_t maskblocked, maskold, maskunblocked; if (!isinitialized) { errno = EINVAL; return -1; } if ((sigprocmask(SIG_SETMASK, NULL, &maskblocked) == -1) || (sigaddset(&maskblocked, signum) == -1) || (sigprocmask(SIG_SETMASK, NULL, &maskunblocked) == -1) || (sigdelset(&maskunblocked, signum) == -1) || (sigprocmask(SIG_SETMASK, &maskblocked, &maskold) == -1)) return -1; while(sigreceived == 0) sigsuspend(&maskunblocked); sigreceived = 0; return sigprocmask(SIG_SETMASK, &maskold, NULL); }
simplesuspendtest.c
#include#include #include int initsuspend(int signo); int restore(void); int simplesuspend(void); int main(void) { fprintf(stderr, "This is process %ld\n", (long)getpid()); for ( ; ; ) { if (initsuspend(SIGUSR1)) { perror("Failed to setup handler for SIGUSR1"); return 1; } fprintf(stderr, "Waiting for signal\n"); if (simplesuspend()) { perror("Failed to suspend for signal"); return 1; } fprintf(stderr, "Got signal\n"); if (restore()) { perror("Failed to restore original handler"); return 1; } } return 1; }
Program 8.11 countsignals.c
#include#include #include int main(void) { int signalcount = 0; int signo; int signum = SIGUSR1; sigset_t sigset; if ((sigemptyset(&sigset) == -1) || (sigaddset(&sigset, signum) == -1) || (sigprocmask(SIG_BLOCK, &sigset, NULL) == -1)) perror("Failed to block signals before sigwait"); fprintf(stderr, "This process has ID %ld\n", (long)getpid()); for ( ; ; ) { if (sigwait(&sigset, &signo) == -1) { perror("Failed to wait using sigwait"); return 1; } signalcount++; fprintf(stderr, "Number of signals so far: %d\n", signalcount); } }
Result
Program 8.7 simplesuspend.c
Program 8.11 countsignals.c
Lab 17 siglongjmp
Content
Program 8.12, P.287
Program 8.12 sigjmp.c
Code to set up a signal handler that returns to the main loop when Ctrl-C is typed.
Source
Program 8.12 sigjmp.c
#include#include #include #include static sigjmp_buf jmpbuf; static volatile sig_atomic_t jumpok = 0; /* ARGSUSED */ static void chandler(int signo) { if (jumpok == 0) return; siglongjmp(jmpbuf, 1); } int main(void) { struct sigaction act; act.sa_flags = 0; act.sa_handler = chandler; if ((sigemptyset(&act.sa_mask) == -1) || (sigaction(SIGINT, &act, NULL) == -1)) { perror("Failed to set up SIGINT handler"); return 1; } /* stuff goes here */ fprintf(stderr, "This is process %ld\n", (long)getpid()); if (sigsetjmp(jmpbuf, 1)) fprintf(stderr, "\nReturned to main loop due to ^c\n"); jumpok = 1; for ( ; ; ) ; /* main loop goes here */ }
Result
Program 8.12 sigjmp.c
Lab 18 POSIX Times
Content
Example 9.2, P.303
Program 9.1, P.307
Program 9.4, P.312
Example 9.2 simpletiming.c
The following program calculates the wall-clock time that it takes to execute function_to_time.
Program 9.1 gettimeofdaytiming.c
A program that measures the running time of a function by using gettimeofday.
Program 9.4 cpufraction.c
A program that calculates the CPU time in seconds for function_to_time and its fraction of total.
Source
functiontotime.c
#include#include void function_to_time() { int i; for (i=0;i<100000000;i++) ; } Example 9.2 simpletiming.c #include #include void function_to_time(void); int main(void) { time_t tstart; tstart = time(NULL); function_to_time(); printf("function_to_time took %f seconds of elapsed time\n", difftime(time(NULL), tstart)); return 0; }
Program 9.1 gettimeofdaytiming.c
#include#include #define MILLION 1000000L void function_to_time(void); int main(void) { long timedif; struct timeval tpend; struct timeval tpstart; if (gettimeofday(&tpstart, NULL)) { fprintf(stderr, "Failed to get start time\n"); return 1; } function_to_time(); /* timed code goes here */ if (gettimeofday(&tpend, NULL)) { fprintf(stderr, "Failed to get end time\n"); return 1; } timedif = MILLION*(tpend.tv_sec - tpstart.tv_sec) + tpend.tv_usec - tpstart.tv_usec; printf("The function_to_time took %ld microseconds\n", timedif); return 0; }
Program 9.4 cpufraction.c
#include#include #include #include void function_to_time(void); int main(void) { double clockticks, cticks; clock_t tcend, tcstart; struct tms tmend, tmstart; if ((clockticks = (double) sysconf(_SC_CLK_TCK)) == -1) { perror("Failed to determine clock ticks per second"); return 1; } printf("The number of ticks per second is %f\n", clockticks); if (clockticks == 0) { fprintf(stderr, "The number of ticks per second is invalid\n"); return 1; } if ((tcstart = times(&tmstart)) == -1) { perror("Failed to get start time"); return 1; } function_to_time(); if ((tcend = times(&tmend)) == -1) { perror("Failed to get end times"); return 1; } cticks = tmend.tms_utime + tmend.tms_stime - tmstart.tms_utime - tmstart.tms_stime; printf("Total CPU time for operation is %f seconds\n", cticks/clockticks); if ((tcend <= tcstart) || (tcend < 0) || (tcstart < 0)) { fprintf(stderr, "Tick time wrapped, couldn't calculate fraction\n"); return 1; } printf("Fraction of CPU time used is %f\n", cticks/(tcend - tcstart)); return 0; }
Result
Example 9.2 simpletiming.c
Program 9.1 gettimeofdaytiming.c
Program 9.4 cpufraction.c
Lab 19 Interval Timer
Content
Program 9.7, P.318
Program 9.12, P.329
Program 9.7 periodicasterisk.c
A program that prints an asterisk for each two seconds of CPU time used.
Program 9.12 tmrtimer.c
A program that uses a POSIX:TMR timer to measure the running time of a function.
Source
Program 9.7 periodicasterisk.c
#include#include #include #include #include struct timeval timenow; /* ARGSUSED */ static void myhandler(int s) { gettimeofday(&timenow, NULL); printf("\nmyhandler time is %ld seconds\n", timenow.tv_sec); char aster = '*'; int errsave; errsave = errno; write(STDERR_FILENO, &aster, 1); errno = errsave; } static int setupinterrupt(void) { /* set up myhandler for SIGPROF */ gettimeofday(&timenow, NULL); printf("setupinterrupt time is %ld seconds\n", timenow.tv_sec); struct sigaction act; act.sa_handler = myhandler; act.sa_flags = 0; return (sigemptyset(&act.sa_mask) || sigaction(SIGPROF, &act, NULL)); } static int setupitimer(void) { /* set ITIMER_PROF for 2-second intervals */ struct itimerval value; value.it_interval.tv_sec = 2; value.it_interval.tv_usec = 0; value.it_value = value.it_interval; return (setitimer(ITIMER_PROF, &value, NULL)); } int main(void) { if (setupinterrupt()) { perror("Failed to set up handler for SIGPROF"); return 1; } if (setupitimer() == -1) { perror("Failed to set up the ITIMER_PROF interval timer"); return 1; } for ( ; ; ); /* execute rest of main program here */ }
Program 9.12 tmrtimer.c
#include#include #include #define MILLION 1000000L #define THOUSAND 1000 void function_to_time(void); int main(void) { long diftime; struct itimerspec nvalue, ovalue; timer_t timeid; if (timer_create(CLOCK_REALTIME, NULL, &timeid) == -1) { perror("Failed to create a timer based on CLOCK_REALTIME"); return 1; } ovalue.it_interval.tv_sec = 0; ovalue.it_interval.tv_nsec = 0; ovalue.it_value.tv_sec = MILLION; /* a large number */ ovalue.it_value.tv_nsec = 0; if (timer_settime(timeid, 0, &ovalue, NULL) == -1) { perror("Failed to set interval timer"); return 1; } function_to_time(); /* timed code goes here */ if (timer_gettime(timeid, &nvalue) == -1) { perror("Failed to get interval timer value"); return 1; } diftime = MILLION*(ovalue.it_value.tv_sec - nvalue.it_value.tv_sec) + (ovalue.it_value.tv_nsec - nvalue.it_value.tv_nsec)/THOUSAND; printf("The function_to_time took %ld microseconds or %f seconds.\n", diftime, diftime/(double)MILLION); return 0; }
Result
Program 9.7 periodicasterisk.c
Program 9.12 tmrtimer.c
Lab 20 Threads
Content
Create and Passing parameter, Program 12.2, P.414
Condition variable, Program 13.13, P.472
Program 12.2 monitorfd.c
A function to monitor an array of file descriptors, using a separate thread for each descriptor.
Program 13.13 tbarrier.c
Implementation of a thread-safe barrier.
Source
Program 12.2 monitorfd.c
#include#include #include #include <string.h> void *processfd(void *arg); void monitorfd(int fd[], int numfds) { /* create threads to monitor fds */ int error, i; pthread_t *tid; if ((tid = (pthread_t *)calloc(numfds, sizeof(pthread_t))) == NULL) { perror("Failed to allocate space for thread IDs"); return; } for (i = 0; i < numfds; i++) /* create a thread for each file descriptor */ if (error = pthread_create(tid + i, NULL, processfd, (fd + i))) { fprintf(stderr, "Failed to create thread %d: %s\n", i, strerror(error)); tid[i] = pthread_self(); } for (i = 0; i < numfds; i++) { if (pthread_equal(pthread_self(), tid[i])) continue; if (error = pthread_join(tid[i], NULL)) fprintf(stderr, "Failed to join thread %d: %s\n", i, strerror(error)); } free(tid); return; }
monitorfdtest.c
#include#include #include void monitorfd(int fd[], int numfds); void docommand(char *buf, int len) { fprintf(stderr,"Got %.*s",len,buf); } int main(int argc, char *argv[]) { int fd[2]; if (argc != 3) { fprintf(stderr,"Usage: %s file1 file2\n",argv[0]); return 1; } if ( (fd[0] = open(argv[1],O_RDONLY)) < 0) { fprintf(stderr,"Error opening file %s\n",argv[1]); return 1; } if ( (fd[1] = open(argv[2],O_RDONLY)) < 0) { fprintf(stderr,"Error opening file %s\n",argv[2]); return 1; } monitorfd(fd,2); return 0; }
Program 13.13 tbarrier.c
#include#include static pthread_cond_t bcond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t bmutex = PTHREAD_MUTEX_INITIALIZER; static int count = 0; static int limit = 0; int initbarrier(int n) { /* initialize the barrier to be size n */ int error; if (error = pthread_mutex_lock(&bmutex)) /* couldn't lock, give up */ return error; if (limit != 0) { /* barrier can only be initialized once */ pthread_mutex_unlock(&bmutex); return EINVAL; } limit = n; return pthread_mutex_unlock(&bmutex); } int waitbarrier(void) { /* wait at the barrier until all n threads arrive */ int berror = 0; int error; if (error = pthread_mutex_lock(&bmutex)) /* couldn't lock, give up */ return error; if (limit <= 0) { /* make sure barrier initialized */ pthread_mutex_unlock(&bmutex); return EINVAL; } count++; while ((count < limit) && !berror) berror = pthread_cond_wait(&bcond, &bmutex); if (!berror) berror = pthread_cond_broadcast(&bcond); /* wake up everyone */ error = pthread_mutex_unlock(&bmutex); if (berror) return berror; return error; }
tbarriertest.c
#include#include int initbarrier(int n); int waitbarrier(); /* ARGSUSED */ static void *printthread(void *arg) { fprintf(stderr,"This is the first print of thread %d\n", (int)pthread_self()); waitbarrier(); fprintf(stderr,"This is the second print of thread %d\n", (int)pthread_self()); return NULL; } int main(void) { pthread_t t0,t1,t2; if (initbarrier(3)) { fprintf(stderr,"Error initilizing barrier\n"); return 1; } if (pthread_create(&t0,NULL,printthread,NULL)) fprintf(stderr,"Error creating thread 0.\n"); if (pthread_create(&t1,NULL,printthread,NULL)) fprintf(stderr,"Error creating thread 1.\n"); if (pthread_create(&t2,NULL,printthread,NULL)) fprintf(stderr,"Error creating thread 2.\n"); if (pthread_join(t0,NULL)) fprintf(stderr,"Error joining thread 0.\n"); if (pthread_join(t1,NULL)) fprintf(stderr,"Error joining thread 1.\n"); if (pthread_join(t2,NULL)) fprintf(stderr,"Error joining thread 2.\n"); fprintf(stderr,"All threads complete.\n"); return 0; }
Result
Please create 2 files in the running environment!
monitorfdtest.c
tbarriertest.c
Lab 21 Socket Programming
Content
Server and Client, Program 18.2, 18.3, P.623, 624
Program 18.9, find IP address for www.scut.edu.cn
Sever and Client in UDP, Program 20.1, 20.2, P.698,699
TCP ping, Excercises 18.10, P.652,
UDP getdayandtime, Exercise 20.10, P.729 *
Program 18.2 serverp.c
A server program that forks a child to handle communication.
Program 18.3 client.c
A client that uses UICI for communication.
Program 20.1 server_udp.c
A server program writes sender information and the received message to its standard output.
Program 20.2 client_udp.c
A client program that sends a request containing its process ID.
Program 18.10 addr2name_gethostbyaddr.c
An implementation of addr2name using gethostbyaddr.
Source
uiciname.h
/* uiciname.h name resolution functions */ #includein.h> #define REENTRANT_NONE 0 #define REENTRANT_R 1 #define REENTRANT_MUTEX 2 #define REENTRANT_POSIX 3 int name2addr(char *name, in_addr_t *addrp); void addr2name(struct in_addr addr, char *name, int namelen);
uiciname.c
/* uiciname.c name resolution functions */ #include#include #include <string.h> #include #include #include "uiciname.h" #ifndef REENTRANCY #define REENTRANCY REENTRANT_NONE #endif #if REENTRANCY==REENTRANT_MUTEX #include static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; #endif #if REENTRANCY==REENTRANT_NONE /* Convert struct in_addr to a host name */ void addr2name(struct in_addr addr, char *name, int namelen) { struct hostent *hostptr; hostptr = gethostbyaddr((char *)&addr, 4, AF_INET); if (hostptr == NULL) strncpy(name, inet_ntoa(addr), namelen-1); else strncpy(name, hostptr->h_name, namelen-1); name[namelen-1] = 0; } /* Return -1 on error, 0 on success */ int name2addr(char *name, in_addr_t *addrp) { struct hostent *hp; if (isdigit((int)(*name))) *addrp = inet_addr(name); else { hp = gethostbyname(name); if (hp == NULL) return -1; memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length); } return 0; } #elif REENTRANCY==REENTRANT_R #define GETHOST_BUFSIZE 8192 void addr2name(struct in_addr addr, char *name, int namelen) { char buf[GETHOST_BUFSIZE]; int h_error; struct hostent *hp; struct hostent result; hp = gethostbyaddr_r((char *)&addr, 4, AF_INET, &result, buf, GETHOST_BUFSIZE, &h_error); if (hp == NULL) strncpy(name, inet_ntoa(addr), namelen-1); else strncpy(name, hp->h_name, namelen-1); name[namelen-1] = 0; } /* Return -1 on error, 0 on success */ int name2addr(char *name, in_addr_t *addrp) { char buf[GETHOST_BUFSIZE]; int h_error; struct hostent *hp; struct hostent result; if (isdigit((int)(*name))) *addrp = inet_addr(name); else { hp = gethostbyname_r(name, &result, buf, GETHOST_BUFSIZE, &h_error); if (hp == NULL) return -1; memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length); } return 0; } #elif REENTRANCY==REENTRANT_MUTEX /* Convert struct in_addr to a host name */ void addr2name(struct in_addr addr, char *name, int namelen) { struct hostent *hostptr; if (pthread_mutex_lock(&mutex) == -1) { strncpy(name, inet_ntoa(addr), namelen-1); name[namelen-1] = 0; return; } hostptr = gethostbyaddr((char *)&addr, 4, AF_INET); if (hostptr == NULL) strncpy(name, inet_ntoa(addr), namelen-1); else strncpy(name, hostptr->h_name, namelen-1); pthread_mutex_unlock(&mutex); name[namelen-1] = 0; } /* Return -1 on error, 0 on success */ int name2addr(char *name, in_addr_t *addrp) { struct hostent *hp; if (isdigit((int)(*name))) *addrp = inet_addr(name); else { if (pthread_mutex_lock(&mutex) == -1) return -1; hp = gethostbyname(name); if (hp == NULL) { pthread_mutex_unlock(&mutex); return -1; } memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length); pthread_mutex_unlock(&mutex); } return 0; } #elif REENTRANCY==REENTRANT_POSIX /* Convert struct in_addr to a host name */ void addr2name(struct in_addr addr, char *name, int namelen) { struct sockaddr_in saddr; saddr.sin_family = AF_INET; saddr.sin_port = 0; saddr.sin_addr = addr; if (getnameinfo((struct sockaddr *)&saddr, sizeof(saddr), name, namelen, NULL, 0, 0) != 0) { strncpy(name, inet_ntoa(addr), namelen-1); name[namelen-1] = 0; } } /* Return -1 on error, 0 on success */ int name2addr(char *name, in_addr_t *addrp) { struct addrinfo hints; struct addrinfo *res; struct sockaddr_in *saddrp; hints.ai_flags = AI_PASSIVE; hints.ai_family = PF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; hints.ai_addrlen = 0; hints.ai_canonname = NULL; hints.ai_addr = NULL; hints.ai_next = NULL; if (getaddrinfo(name, NULL, &hints, &res) != 0) return -1; saddrp = (struct sockaddr_in *)(res->ai_addr); memcpy(addrp, &saddrp->sin_addr.s_addr, 4); freeaddrinfo(res); return 0; } #endif
uici.h
/*********************************** uici.h **************************/ /* Prototypes for the three public UICI functions */ /*********************************************************************/ #define UPORT typedef unsigned short u_port_t; int u_open(u_port_t port); int u_accept(int fd, char *hostn, int hostnsize); int u_connect(u_port_t port, char *hostn);
uici.c
/* uici.c sockets implementation */ #include#include #include <string.h> #include #include select.h> #include #include "uici.h" #include "uiciname.h" #ifndef MAXBACKLOG #define MAXBACKLOG 50 #endif /* * u_igniore_sigpipe * Ignore SIGPIPE if the default action is in effect. * * returns: 0 if successful * -1 on error and sets errno */ static int u_ignore_sigpipe() { struct sigaction act; if (sigaction(SIGPIPE, (struct sigaction *)NULL, &act) == -1) return -1; if (act.sa_handler == SIG_DFL) { act.sa_handler = SIG_IGN; if (sigaction(SIGPIPE, &act, (struct sigaction *)NULL) == -1) return -1; } return 0; } /* * u_open * Return a file descriptor, which is bound to the given port. * parameter: * s = number of port to bind to * returns: file descriptor if successful * -1 on error and sets errno */ int u_open(u_port_t port) { int error; struct sockaddr_in server; int sock; int true = 1; if ((u_ignore_sigpipe() == -1) || ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)) return -1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&true, sizeof(true)) == -1) { error = errno; while ((close(sock) == -1) && (errno == EINTR)); errno = error; return -1; } server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons((short)port); if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1) || (listen(sock, MAXBACKLOG) == -1)) { error = errno; while ((close(sock) == -1) && (errno == EINTR)); errno = error; return -1; } return sock; } /* * u_accept * Wait for a connection request from a host on a specified port. * * parameters: * fd = file descriptor previously bound to listening port * hostn = a buffer that will hold the name of the remote host * hostnsize = size of hostn buffer * returns: a communication file descriptor on success * hostn is filled with the name of the remote host. * -1 on error with errno set * * comments: This function is used by the server to wait for a * communication. It blocks until a remote request is received * from the port bound to the given file descriptor. * hostn is filled with an ASCII string containing the remote * host name. It must point to a buffer of size at least hostnsize. * If the name does not fit, as much of the name as is possible is put * into the buffer. * If hostn is NULL or hostnsize <= 0, no hostname is copied. */ int u_accept(int fd, char *hostn, int hostnsize) { int len = sizeof(struct sockaddr); struct sockaddr_in netclient; int retval; while (((retval = accept(fd, (struct sockaddr *)(&netclient), &len)) == -1) && (errno == EINTR)) ; if ((retval == -1) || (hostn == NULL) || (hostnsize <= 0)) return retval; addr2name(netclient.sin_addr, hostn, hostnsize); return retval; } /* * u_connect * Initiate communication with a remote server. * * parameters: * port = well-known port on remote server * hostn = character string giving the Internet name of remote host * returns: a communication file descriptor if successful * -1 on error with errno set */ int u_connect(u_port_t port, char *hostn) { int error; int retval; struct sockaddr_in server; int sock; fd_set sockset; if (name2addr(hostn,&(server.sin_addr.s_addr)) == -1) { errno = EINVAL; return -1; } server.sin_port = htons((short)port); server.sin_family = AF_INET; if ((u_ignore_sigpipe() == -1) || ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)) return -1; if (((retval = connect(sock, (struct sockaddr *)&server, sizeof(server))) == -1) && ((errno == EINTR) || (errno == EALREADY))) { FD_ZERO(&sockset); FD_SET(sock, &sockset); while ( ((retval = select(sock+1, NULL, &sockset, NULL, NULL)) == -1) && (errno == EINTR) ) { FD_ZERO(&sockset); FD_SET(sock, &sockset); } } if (retval == -1) { error = errno; while ((close(sock) == -1) && (errno == EINTR)); errno = error; return -1; } return sock; }
Program 18.2 serverp.c
#include#include #include #include #include <string.h> #include #include #include #include "restart.h" #include "uici.h" int main(int argc, char *argv[]) { int bytescopied; pid_t child; char client[MAX_CANON]; int communfd; int listenfd; u_port_t portnumber; if (argc != 2) { fprintf(stderr, "Usage: %s port\n", argv[0]); return 1; } portnumber = (u_port_t) atoi(argv[1]); if ((listenfd = u_open(portnumber)) == -1) { perror("Failed to create listening endpoint"); return 1; } fprintf(stderr, "[%ld]: Waiting for connection on port %d\n", (long)getpid(), (int)portnumber); for ( ; ; ) { if ((communfd = u_accept(listenfd, client, MAX_CANON)) == -1) { perror("Failed to accept connection"); continue; } fprintf(stderr, "[%ld]:connected to %s\n", (long)getpid(), client); if ((child = fork()) == -1) perror("Failed to fork a child"); if (child == 0) { /* child code */ if (r_close(listenfd) == -1) { fprintf(stderr, "[%ld]:failed to close listenfd: %s\n", (long)getpid(), strerror(errno)); return 1; } bytescopied = copyfile(communfd, STDOUT_FILENO); fprintf(stderr, "[%ld]:received %d bytes\n", (long)getpid(), bytescopied); return 0; } if (r_close(communfd) == -1) /* parent code */ fprintf(stderr, "[%ld]:failed to close communfd: %s\n", (long)getpid(), strerror(errno)); while (r_waitpid(-1, NULL, WNOHANG) > 0) ; /* clean up zombies */ } }
Program 18.3 client.c
#include#include #include #include "restart.h" #include "uici.h" int main(int argc, char *argv[]) { int bytescopied; int communfd; u_port_t portnumber; if (argc != 3) { fprintf(stderr, "Usage: %s host port\n", argv[0]); return 1; } portnumber = (u_port_t)atoi(argv[2]); if ((communfd = u_connect(portnumber, argv[1])) == -1) { perror("Failed to make connection"); return 1; } fprintf(stderr, "[%ld]:connected %s\n", (long)getpid(), argv[1]); bytescopied = copyfile(STDIN_FILENO, communfd); fprintf(stderr, "[%ld]:sent %d bytes\n", (long)getpid(), bytescopied); return 0; }
uiciudp.h
#includein.h> #ifndef UPORT typedef unsigned short u_port_t; #endif #define UPORT #ifndef ETIME #define ETIME ETIMEDOUT #endif typedef struct sockaddr_in u_buf_t; int u_openudp(u_port_t port); void u_gethostname(u_buf_t *ubufp, char *hostn, int hostnsize); void u_gethostinfo(u_buf_t *ubufp, char *info, int infosize); int u_comparehost(u_buf_t *ubufp, char *hostn, u_port_t port); ssize_t u_sendtohost(int fd, void *buf, size_t nbyte, char *hostn, u_port_t port); ssize_t u_sendto(int fd, void *buf, size_t nbyte, u_buf_t *ubufp); ssize_t u_recvfrom(int fd, void *buf, size_t nbyte, u_buf_t *ubufp); ssize_t u_recvfromtimed(int fd, void *buf, size_t nbyte, u_buf_t *ubufp, double time); int u_join(char *IP_address, u_port_t port, u_buf_t *ubufp); int u_leave(int mcastfd, u_buf_t *ubufp);
uiciudp.c
/* uiciudp.c udp sockets implementation */ #include#include #include <string.h> #include #include #include #include #include "restart.h" #include "uiciname.h" #include "uiciudp.h" /* * u_openudp * Return a file descriptor. * It is bound to the given port if the port is positive. * * parameter: * port = number of port to bind to * returns: file descriptor if successful * -1 on error and sets errno */ int u_openudp(u_port_t port) { int error; int one = 1; struct sockaddr_in server; int sock; if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) return -1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) { error = errno; r_close(sock); errno = error; return -1; } if (port > 0) { server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons((short)port); if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1) { error = errno; r_close(sock); errno = error; return -1; } } return sock; } /* * u_recvfrom * * Retrieve information from a file descriptor. * * parameters: * fd = socket file descriptor * buf = buffer that receives the data * nbytes = number of bytes to retrieve * ubufp = a pointer to a buffer of type u_buf_t * returns: * the number of bytes read if successful. * ubufp is filled with information about the sending host and port * -1 on error and sets errno */ ssize_t u_recvfrom(int fd, void *buf, size_t nbytes, u_buf_t *ubufp) { int len; struct sockaddr *remote; int retval; len = sizeof (struct sockaddr_in); remote = (struct sockaddr *)ubufp; while (((retval = recvfrom(fd, buf, nbytes, 0, remote, &len)) == -1) && (errno == EINTR)) ; return retval; } /* * u_recvfromtimed * * Retrieve information from a file descriptor with a timeout. * * parameters: * fd = socket file descriptor * buf = buffer to receive the data * nbytes = number of bytes to retrieve * ubufp = a pointer to a buffer of type u_buf_t * seconds = timeout in seconds * returns: * number of bytes received if successful * -1 on error and sets errno */ ssize_t u_recvfromtimed(int fd, void *buf, size_t nbytes, u_buf_t *ubufp, double seconds) { int len; struct sockaddr *remote; int retval; struct timeval timedone; timedone = add2currenttime(seconds); if (waitfdtimed(fd, timedone) == -1) return (ssize_t)(-1); len = sizeof (struct sockaddr_in); remote = (struct sockaddr *)ubufp; while (((retval = recvfrom(fd, buf, nbytes, 0, remote, &len)) == -1) && (errno == EINTR)) ; return retval; } /* * u_gethostname * * Get the host name from a buffer of type u_buf_t * * parameters: * ubufp = a pointer to a buffer of type u_buf_t that was * filled by u_recvfrom * hostn = a buffer of size hostnsize * hostsize = the size of the hostn buffer * returns: * hostn is filled with the name of the host, possibly truncated. */ void u_gethostname(u_buf_t *ubufp, char *hostn, int hostnsize) { struct sockaddr_in *remotep; remotep = (struct sockaddr_in *)ubufp; addr2name(remotep->sin_addr, hostn, hostnsize); } /* * u_gethostinfo * * Get a printable string containing the host name and port * * parameters: * ubufp = a pointer to a buffer of type u_buf_t that was * filled by u_recvfrom * info = a buffer to hold the returned string * infosize = the size of the info buffer * returns: * a string is put in info, possibly truncated */ void u_gethostinfo(u_buf_t *ubufp, char *info, int infosize) { int len; int portnumber; portnumber = ntohs(ubufp->sin_port); len = snprintf(info, infosize, "port number is %d on host ", portnumber); info[infosize-1] = 0; /* in case name not fit */ if (len >= infosize) return; u_gethostname(ubufp, info+len, infosize-len); } /* * u_comparehost * * Compare the given host and port with the info in a u_buf_t structure * * parameters: * ubufp = a pointer to a buffer of type u_buf_t that was * filled by u_recvfrom * hostn = a string representing the host name * port = a port number * returns: * 1 if match * 0 if no match */ int u_comparehost(u_buf_t *ubufp, char *hostn, u_port_t port) { in_addr_t addr; struct sockaddr_in *remotep; remotep = (struct sockaddr_in *)ubufp; if ((port != ntohs(remotep->sin_port)) || (name2addr(hostn, &addr) == -1) || (memcmp(&(remotep->sin_addr.s_addr), &addr, sizeof(in_addr_t)) != 0)) return 0; return 1; } /* * u_sendto * * Send information atomically to a remote host, using the buffer filled in * by recvfrom * * This is almost the same as sendto except that * it retries if interrupted by a signal and * the length of the buffer indicating the destination is not passed * * parameters: * fd = file descriptor * buf = buffer to be output * nbytes = number of bytes to send * ubufp = a pointer to a buffer of type u_buf_t that was * filled by u_recvfrom * returns: * the number of bytes that were sent (may not have been received) * -1 on error and sets errno */ ssize_t u_sendto(int fd, void *buf, size_t nbytes, u_buf_t *ubufp) { int len; struct sockaddr *remotep; int retval; len = sizeof(struct sockaddr_in); remotep = (struct sockaddr *)ubufp; while (((retval = sendto(fd, buf, nbytes, 0, remotep, len)) == -1) && (errno == EINTR)) ; return retval; } /* * u_sendtohost * * Send information atomically to a remote host given the host name and port * * parameters: * fd = file descriptor * buf = buffer to be output * nbyte = number of bytes to send * port = the port number to send to * hostn = a string containing the name of the destination host * returns: * the number of bytes that were sent (may not have been received) * -1 on error and sets errno */ ssize_t u_sendtohost(int fd, void *buf, size_t nbytes, char *hostn, u_port_t port) { struct sockaddr_in remote; if (name2addr(hostn, &(remote.sin_addr.s_addr)) == -1) { errno = EINVAL; return -1; } remote.sin_port = htons((short)port); remote.sin_family = AF_INET; return u_sendto(fd, buf, nbytes, &remote); } /* * u_join * * Join a multicast group * * parameters: * IP_address = string representing the IP address of the group * port = port number of multicast group * ubufp = buffer to be filled in u_join * returns: * a file descriptor on success * -1 on error and sets errno */ int u_join(char *IP_address, u_port_t port, u_buf_t *ubufp) { int mcastfd; struct ip_mreq tempaddress; if ((mcastfd = u_openudp(port)) == -1) return mcastfd; tempaddress.imr_multiaddr.s_addr = inet_addr(IP_address); tempaddress.imr_interface.s_addr = htonl(INADDR_ANY); /* Join the multicast group. Let kernel choose the interface */ if (setsockopt(mcastfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &tempaddress, sizeof(tempaddress)) == -1) return -1; ubufp->sin_family = AF_INET; ubufp->sin_addr.s_addr = inet_addr(IP_address); ubufp->sin_port = htons((short)port); return mcastfd; } /* This version leaves the group but keeps the file descriptor open and still bound to the same port. It can still receive messages on the port, but only those addressed directly to the given host. */ /* * u_leave * * Leave a multicast group. Messages can still be received on the port * if they are directly addressed to the host. * * parameters: * mcastfd = previously opened file descriptor returned by u_join * ubufp = buffer filled in by previous u_join * returns: * 0 on success * -1 on error with errno set */ int u_leave(int mcastfd, u_buf_t *ubufp) { struct ip_mreq tempaddress; memcpy(&(tempaddress.imr_multiaddr), &(ubufp->sin_addr), sizeof(struct in_addr)); tempaddress.imr_interface.s_addr = htonl(INADDR_ANY); return setsockopt(mcastfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &tempaddress, sizeof(tempaddress)); }
Program 20.1 server_udp.c
#include#include #include <string.h> #include #include "restart.h" #include "uiciudp.h" #define BUFSIZE 1024 int main(int argc, char *argv[]) { char buf[BUFSIZE]; ssize_t bytesread; char hostinfo[BUFSIZE]; u_port_t port; int requestfd; u_buf_t senderinfo; if (argc != 2) { fprintf(stderr, "Usage: %s port\n", argv[0]); return 1; } port = (u_port_t) atoi(argv[1]); /* create communication endpoint */ if ((requestfd = u_openudp(port)) == -1) { perror("Failed to create UDP endpoint"); return 1; } for ( ; ; ) { /* process client requests */ bytesread = u_recvfrom(requestfd, buf, BUFSIZE, &senderinfo); if (bytesread < 0) { perror("Failed to receive request"); continue; } u_gethostinfo(&senderinfo, hostinfo, BUFSIZE); if ((r_write(STDOUT_FILENO, hostinfo, strlen(hostinfo)) == -1) || (r_write(STDOUT_FILENO, buf, bytesread) == -1)) { perror("Failed to echo reply to standard output"); } } }
Program 20.2 client_udp.c
#include#include #include #include <string.h> #include #include "restart.h" #include "uiciudp.h" #define BUFSIZE 1024 int main(int argc, char *argv[]) { ssize_t byteswritten; char request[BUFSIZE]; int requestfd; int rlen; u_port_t serverport; if (argc != 3) { fprintf(stderr, "Usage: %s servername serverport\n", argv[0]); return 1; } serverport = (u_port_t) atoi(argv[2]); if ((requestfd = u_openudp(0)) == -1) { /* create unbound UDP endpoint */ perror("Failed to create UDP endpoint"); return 1; } sprintf(request, "[%ld]\n", (long)getpid()); /* create a request */ rlen = strlen(request); /* use simple-request protocol to send a request to (server, serverport) */ byteswritten = u_sendtohost(requestfd, request, rlen, argv[1], serverport); if (byteswritten == -1) perror("Failed to send"); if (r_close(requestfd) == -1 || byteswritten == -1) return 1; return 0; }
Program 18.10 addr2name_gethostbyaddr.c
//name2addr_gethostbyname.c #include#include #include <string.h> #include #include #include in.h> #include #include #include int name2addr(char *name, in_addr_t *addrp) { struct hostent *hp; if (isdigit((int)(*name))) *addrp = inet_addr(name); else { hp = gethostbyname(name); if (hp == NULL) return -1; memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length); } return 0; } int main() { char * name = "www.scut.edu.cn"; in_addr_t ip; name2addr(name, &ip); unsigned char tmp[4]; memcpy(tmp, (char *)&ip, 4); printf(">>> %d.%d.%d.%d\n", tmp[0], tmp[1], tmp[2], tmp[3]); return 0; }
Result
Program 18.2 serverp.c
client.c &server.c
Program 20.1 server_udp.c
client_udp.c & server_udp.c
Program 18.10 addr2name_gethostbyaddr.c
小结
资源下载:http://files.cnblogs.com/yongfeng/UnixCode.zip