Unix-Linux编程实践教程——第十一章

来源:互联网 发布:手机隔墙听软件 编辑:程序博客网 时间:2024/05/29 04:33

章节概要

本章节介绍进程间管道通信以及套接字SOCKET编程

mylinux.h

/*********************************************************    > File Name: mylinux.h    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月16日 星期一 13时49分36秒 *********************************************************/#ifndef _MYLINUX_H_#define _MYLINUX_H_#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<wait.h>#include<signal.h>#include<string.h>#include<sys/types.h>#include<sys/stat.h>#include<sys/socket.h>#include<netinet/in.h>#include<netdb.h>#include<fcntl.h>#include<time.h>#include<utmp.h>#define oops(m,x) {perror(m);exit(x);}void fatal(char* mess){    fprintf(stderr,"Error: %s\n",mess);    exit(1);}#endif

tinybc.c

/**********************************************************    > File Name: tinybc.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 20171016日 星期一 132546**********************************************************/#include "mylinux.h"//这里要理清管道的出入void be_dc(int in[2],int out[2]){    //管道读取端连接到stdin    if(dup2(in[0],0)==-1) oops("dc,cannot redirect stdin",3);    close(in[0]);    close(in[1]);    //管道输入端连接到stdout    if(dup2(out[1],1)==-1) oops("dc,cannot redirect stdout",4);    close(out[1]);    close(out[0]);    execlp("dc","dc","-",NULL);    oops("Cannot run dc",5);}void be_bc(int todc[2],int fromdc[2]){    int num1,num2;    char operation[BUFSIZ],message[BUFSIZ];    FILE *fpout,*fpin;    close(todc[0]); //won't read from pipe to dc    close(fromdc[1]);//won't write to pipe from dc    fpout = fdopen(todc[1],"w");    fpin = fdopen(fromdc[0],"r");    if(fpout==NULL||fpin==NULL) fatal("Error convering pipes to streams");    while(printf("tinybc:"),fgets(message,BUFSIZ,stdin)!=NULL){        if(sscanf(message,"%d%[-+*/^%]%d",&num1,operation,&num2)!=3){            printf("syntax error\n");            continue;        }        if(fprintf(fpout,"%d\n%d\n%c\np\n",num1,num2,*operation)==EOF) fatal("Error writing");        fflush(fpout);        if(fgets(message,BUFSIZ,fpin)==NULL) break;        printf("%d %c %d = %s",num1,*operation,num2,message);    }    fclose(fpout);    fclose(fpin);}//由于管道的阻塞读取,所以会在父进程运行完be_bc后,子进程be_dc才开始执行int main(){    int pid,todc[2],fromdc[2];    if(pipe(todc)==-1||pipe(fromdc)==-1){        oops("pipe failed",1);    }    if((pid=fork())==-1){        oops("Cannot fork",2);    }    if(pid==0) be_dc(todc,fromdc);    else{        be_bc(todc,fromdc);        //这里的wait有什么用?——等待子进程的运算结束以及输出        wait(NULL);    }}

popendemo.c

/************************************************************    > File Name: popendemo.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月16日 星期一 14时10分37秒 *********************************************************/#include "mylinux.h"int main(){    FILE *fp;    char buf[100];    int i=0;    fp = popen("ps|sort","r");    while(fgets(buf,100,fp)!=NULL){        printf("%3d %s",i++,buf);    }    pclose(fp);    return 0;}

popen_ex3.c

/************************************************************    > File Name: popen_ex3.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月16日 星期一 14时13分04秒 ************************************************************/#include "mylinux.h"int main(){    FILE *fp;    fp = popen("mail admin backup","w");    fprintf(fp,"Error with backup!\n");    pclose(fp);    return 0;}

popen.c

/************************************************************    > File Name: popen.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 20171016日 星期一 142249************************************************************/#include "mylinux.h"#define READ 0#define WRITE 1//popen的简单实现FILE* popen(const char *command,const char *mode){    int pfp[2],pid;    int parent_end,child_end;    if(*mode=='r'){        parent_end = READ;        child_end = WRITE;    }else if(*mode=='w'){        parent_end = WRITE;        child_end = READ;    }else return NULL;    if(pipe(pfp)==-1){        return NULL;    }    if((pid=fork())==-1){        close(pfp[0]);        close(pfp[1]);        return NULL;    }    if(pid>0){        if(close(pfp[child_end])==-1){            return NULL;        }        return fdopen(pfp[parent_end],mode);    }    if(close(pfp[parent_end])==-1) exit(1);    if(dup2(pfp[child_end],child_end)==-1) exit(1);     if(close(pfp[child_end])==-1) exit(1);    execl("/bin/sh","sh","-c",command,NULL);    exit(1);}

timeserv.c

一个简单的时间服务器,socket编程参考TCP/IP详解卷一卷二

/***********************************************************    > File Name: timeserv.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月16日 星期一 14时51分43秒 ************************************************************/#include "mylinux.h"#define PORTNUM 13000#define HOSTLEN 256int main(int ac,char *av[]){    struct sockaddr_in saddr;    struct hostent *hp;    char hostname[HOSTLEN];    int sock_id,sock_fd;    FILE *sock_fp;    time_t thetime;    sock_id = socket(PF_INET,SOCK_STREAM,0);    if(sock_id==-1) oops("socket",1);    bzero((void*)&saddr,sizeof(saddr));    //得到主机名    gethostname(hostname,HOSTLEN);    hp = gethostbyname(hostname);    bcopy((void*)hp->h_addr,(void*)&saddr.sin_addr,hp->h_length);    //设置端口号    saddr.sin_port = htons(PORTNUM);    saddr.sin_family = AF_INET;    if(bind(sock_id,(struct sockaddr*)&saddr,sizeof(saddr))!=0) oops("bind",1);    if(listen(sock_id,1)!=0) oops("listen",1);    while(1){        sock_fd = accept(sock_id,NULL,NULL);        printf("Wow!got a call!\n");        if(sock_fd==-1) oops("accept",1);        sock_fp = fdopen(sock_fd,"w");        if(sock_fp==NULL) oops("fdopen",1);        thetime = time(NULL);        fprintf(sock_fp,"the time here is ..");        fprintf(sock_fp,"%s",ctime(&thetime));        fclose(sock_fp);    }    return 0;}