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

来源:互联网 发布:log4j sql日志级别 编辑:程序博客网 时间:2024/06/04 19:51

章节概要

本章节介绍UDP编程以及编写许可证服务器

dgram.c

/*********************************************************    > File Name: dgram.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 12时21分59秒 ********************************************************/#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<arpa/inet.h>#include<netdb.h>#include<string.h>#define HOSTLEN 256int get_internet_address(char* host,int len,int* portp,struct sockaddr_in *addrp){    strncpy(host,inet_ntoa(addrp->sin_addr),len);    *portp = ntohs(addrp->sin_port);    return 0;}//封装int make_internet_address(char* hostname,int port ,struct sockaddr_in *addrp){    struct hostent *hp;    bzero((void*)addrp,sizeof(struct sockaddr_in));    hp = gethostbyname(hostname);    if(hp==NULL) return -1;    bcopy((void*)hp->h_addr,(void*)&addrp->sin_addr,hp->h_length);    addrp->sin_port = htons(port);    addrp->sin_family=AF_INET;    return 0;}//封装服务器端的套接字建立以及绑定int make_dgram_server_socket(int portnum){    struct sockaddr_in saddr;    char hostname[HOSTLEN];    int sock_id;    sock_id = socket(PF_INET,SOCK_DGRAM,0);    if(sock_id==-1) return -1;    gethostname(hostname,HOSTLEN);    printf("hostname :%s",hostname);    make_internet_address(hostname,portnum,&saddr);    if(bind(sock_id,(struct sockaddr*)&saddr,sizeof(saddr))!=0) return -1;    return sock_id;}int make_dgram_client_socket(){    return socket(PF_INET,SOCK_DGRAM,0);}

dgrecv.c

/********************************************************    > File Name: dgrecv.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 11时16分53秒 ********************************************************/#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#define oops(m,x){perror(m);exit(x);}int make_dgram_server_socket(int);int get_internet_address(char*,int,int*,struct sockaddr_in*);void say_who_called(struct sockaddr_in*);int main(int ac,char *av[]){    int port;    int sock;    char buf[BUFSIZ];    ssize_t msglen;    struct sockaddr_in saddr;    socklen_t saddrlen;    if(ac==1||(port=atoi(av[1]))<=0){        fprintf(stderr,"usage:dgrecv portnumber\n");        exit(1);    }    if((sock=make_dgram_server_socket(port))==-1) oops("cannot make socket",2);    saddrlen = sizeof(saddr);    while((msglen=recvfrom(sock,buf,BUFSIZ,0,&saddr,&saddrlen))>0){        buf[msglen]='\0';        printf("dgrecv:got a message:%s\n",buf);        say_who_called(&saddr);    }    return 0;}void say_who_called(struct sockaddr_in *addrp){    char host[BUFSIZ];    int port;    get_internet_address(host,BUFSIZ,&port,addrp);    printf("from:%s:%d\n",host,port);}

dgsend.c

/**********************************************************    > File Name: dgsend.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 11时24分58秒 *********************************************************/#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<string.h>#define oops(m,x){perror(m);exit(x);}int make_dgram_client_socket();int make_internet_address(char*,int,struct sockaddr_in*);int main(int ac,char *av[]){    int sock;    char *msg;    struct sockaddr_in saddr;    if(ac!=4){        fprintf(stderr,"usage:dgsend host port 'message'\n");        exit(1);    }    msg = av[3];    if((sock=make_dgram_client_socket())==-1) oops("cannot make socket",2);    make_internet_address(av[1],atoi(av[2]),&saddr);    if(sendto(sock,msg,strlen(msg),0,&saddr,sizeof(saddr))==-1) oops("sendto failed",3);    return 0;}

dgrecv2.c

/**********************************************************    > File Name: dgrecv2.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 11时16分53秒 ********************************************************/#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<string.h>#include<unistd.h>#define oops(m,x){perror(m);exit(x);}int make_dgram_server_socket(int);int get_internet_address(char*,int,int*,struct sockaddr_in*);void say_who_called(struct sockaddr_in*);void reply_to_sender(int,char*,struct sockaddr_in*,socklen_t);int main(int ac,char *av[]){    int port;    int sock;    char buf[BUFSIZ];    ssize_t msglen;    struct sockaddr_in saddr;    socklen_t saddrlen;    if(ac==1||(port=atoi(av[1]))<=0){        fprintf(stderr,"usage:dgrecv portnumber\n");        exit(1);    }    if((sock=make_dgram_server_socket(port))==-1) oops("cannot make socket",2);    saddrlen = sizeof(saddr);    while((msglen=recvfrom(sock,buf,BUFSIZ,0,&saddr,&saddrlen))>0){        buf[msglen]='\0';        printf("dgrecv:got a message:%s\n",buf);        say_who_called(&saddr);        reply_to_sender(sock,buf,&saddr,saddrlen);    }    return 0;}void say_who_called(struct sockaddr_in *addrp){    char host[BUFSIZ];    int port;    get_internet_address(host,BUFSIZ,&port,addrp);    printf("from:%s:%d\n",host,port);}void reply_to_sender(int sock,char *msg,struct sockaddr_in* addrp,socklen_t len){    char reply[BUFSIZ+BUFSIZ];    sprintf(reply,"Thanks for your %lu char message\n",strlen(msg));    sendto(sock,reply,strlen(reply),0,addrp,len);}

dgsend2.c

/*********************************************************    > File Name: dgsend2.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 11时24分58秒 ********************************************************/#include<stdio.h>#include<stdlib.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<string.h>#define oops(m,x){perror(m);exit(x);}int make_dgram_client_socket();int make_internet_address(char*,int,struct sockaddr_in*);int main(int ac,char *av[]){    int sock;    char *msg;    char buf[BUFSIZ];    struct sockaddr_in saddr;    socklen_t saddrlen;    if(ac!=4){        fprintf(stderr,"usage:dgsend host port 'message'\n");        exit(1);    }    msg = av[3];    if((sock=make_dgram_client_socket())==-1) oops("cannot make socket",2);    make_internet_address(av[1],atoi(av[2]),&saddr);    if(sendto(sock,msg,strlen(msg),0,&saddr,sizeof(saddr))==-1) oops("sendto failed",3);    saddrlen = sizeof(saddr);    int msglen = recvfrom(sock,buf,BUFSIZ,0,&saddr,&saddrlen);    if(msglen<=0)         printf("receive msg err");    else{        buf[msglen]='\0';        printf("receive msg from server:%s\n",buf);    }    return 0;}

lclnt1.c

/*******************************************************    > File Name: lclnt1.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 13时47分59秒 *******************************************************/#include<stdio.h>#include<unistd.h>void do_regular_work(){    printf("SuperSleep version 1.0 Running-Licensed Software\n");    sleep(5);}int main(int ac,char *av[]){    setup();    if(get_ticket()!=0) exit(0);    do_regular_work();    release_ticket();    shut_down();    return 0;}

lclnt_funcs1.c

/*****************************************************    > File Name: lclnt_funcs1.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 13时50分01秒 ******************************************************/#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<netdb.h>#include<string.h>#include<stdlib.h>#include<unistd.h>static int pid = -1;static int sd = -1;static struct sockaddr serv_addr;static socklen_t serv_alen;static char ticket_buf[128];static int have_ticket=0;#define MSGLEN 128#define SERVER_PORTNUM 2020#define HOSTLEN 512#define oops(p) {perror(p);exit(1);}char* do_transaction();void setup(){    char hostname[BUFSIZ];    pid = getpid();    sd = make_dgram_client_socket();    if(sd==-1) oops("Cannot create socket");    gethostname(hostname,HOSTLEN);    make_internet_address(hostname,SERVER_PORTNUM,&serv_addr);    serv_alen = sizeof(serv_addr);}void narrate(char *m1,char *m2){    fprintf(stderr,"CLIENT [%d]:%s %s\n",pid,m1,m2);}void syserr(char *msg){    char buf[MSGLEN];    sprintf(buf,"CLIENT [%d]:%s",pid,msg);    perror(buf);}void shut_down(){    close(sd);}char* do_transaction(char* msg){    static char buf[MSGLEN];    struct sockaddr retaddr;    socklen_t addrlen = sizeof(retaddr);    int ret;    ret = sendto(sd,msg,strlen(msg),0,&serv_addr,serv_alen);    if(ret==-1){        syserr("sendto");        return NULL;    }    ret = recvfrom(sd,buf,MSGLEN,0,&retaddr,&addrlen);    if(ret==-1){        syserr("recvfrom");        return NULL;    }    return buf;}int get_ticket(){    char *response;    char buf[MSGLEN];    if(have_ticket) return 0;    sprintf(buf,"HELO %d",pid);    if((response=do_transaction(buf))==NULL){        return -1;    }    if(strncmp(response,"TICK",4)==0){        strcpy(ticket_buf,response+5);        have_ticket = 1;        narrate("got ticket",ticket_buf);        return 0;    }    if(strncmp(response,"FAIL",4)==0)        narrate("Could not get ticket",response);    else        narrate("Unknown message:",response);    return -1;}int release_ticket(){    char buf[MSGLEN];    char *response;    if(!have_ticket) return 0;    sprintf(buf,"GBYE %s",ticket_buf);    if((response=do_transaction(buf))==NULL) return -1;    if(strncmp(response,"THNX",4)==0){        narrate("released ticket OK","");        return 0;    }    if(strncmp(response,"FAIL",4)==0){        narrate("release failed",response+5);    }else{        narrate("Unknown message:",response);    }    return -1;}

lserv1.c

/***********************************************************    > File Name: lserv1.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 14时23分06秒 *********************************************************/#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<signal.h>#include<sys/errno.h>#define MSGLEN 128int main(int ac,char *av[]){    struct sockaddr_in client_addr;    socklen_t addrlen = sizeof(client_addr);    char buf[MSGLEN];    int ret;    int sock;    sock = setup();    while(1){        addrlen = sizeof(client_addr);        ret = recvfrom(sock,buf,MSGLEN,0,&client_addr,&addrlen);        if(ret!=-1){            buf[ret]='\0';            narrate("GOT:",buf,&client_addr);            handle_request(buf,&client_addr,addrlen);        }else if(errno!=EINTR) perror("recvfrom");    }    return 0;}

lsrv_funcs1.c

/*************************************************************    > File Name: lsrv_funcs1.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 14时27分17秒 ***********************************************************/#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<netdb.h>#include<signal.h>#include<sys/errno.h>#include<string.h>#include<unistd.h>#include<stdlib.h>#include<arpa/inet.h>#define SERVER_PORTNUM 2020#define MSGLEN 128#define TICKET_AVAIL 0#define MAXUSERS 3#define oops(x) {perror(x);exit(-1);}int ticket_array[MAXUSERS];int sd = -1;int num_tickets_out = 0;char *do_hello();char *do_goodbye();void free_all_tickets(){    int i;    for(i=0;i<MAXUSERS;++i){        ticket_array[i]=TICKET_AVAIL;    }}void shut_down(){    close(sd);}void narrate(char *msg1,char *msg2,struct sockaddr_in *clientp){    fprintf(stderr,"\t\tSERVER:%s %s",msg1,msg2);    if(clientp)        fprintf(stderr,"(%s:%d)",inet_ntoa(clientp->sin_addr),ntohs(clientp->sin_port));    putc('\n',stderr);}char *do_hello(char *msg_p){    int x;    static char replybuf[MSGLEN];    if(num_tickets_out>=MAXUSERS) return "FAIL no tickets available";    for(x=0;x<MAXUSERS&&ticket_array[x]!=TICKET_AVAIL;++x);    if(x==MAXUSERS){        narrate("database corrupt","",NULL);        return "FAIL database corupt";    }    ticket_array[x] = atoi(msg_p+5);    sprintf(replybuf,"TICK %d.%d",ticket_array[x],x);    num_tickets_out++;    return replybuf;}char *do_goodbye(char *msg_p){    int pid,slot;    if((sscanf((msg_p+5),"%d.%d",&pid,&slot)!=2)||            (ticket_array[slot]!=pid)){        narrate("Bogus ticket",msg_p+5,NULL);        return "FAIL invalid ticket";    }    ticket_array[slot] = TICKET_AVAIL;    num_tickets_out--;    return "THNX See ya!";}void handle_request(char *req,struct sockaddr_in *client,socklen_t addlen){    char *response;    int ret;    if(strncmp(req,"HELO",4)==0) response = do_hello(req);    else if(strncmp(req,"GBYE",4)==0) response = do_goodbye(req);    else response = "FAIL invalid request";    narrate("SAID:",response,client);    ret = sendto(sd,response,strlen(response),0,client,addlen);    if(ret==-1) perror("SERVER sendto failed");}int setup(){    sd = make_dgram_server_socket(SERVER_PORTNUM);    if(sd==-1) oops("make socket");    free_all_tickets();    return sd;}

lserv2.c

/**********************************************************    > File Name: lserv2.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 14时23分06秒 ********************************************************/#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<signal.h>#include<sys/errno.h>#define MSGLEN 128int main(int ac,char *av[]){    struct sockaddr_in client_addr;    socklen_t addrlen = sizeof(client_addr);    char buf[MSGLEN];    int ret;    int sock;    unsigned time_left;    sock = setup();    signal(SIGALRM,ticket_reclaim);    alarm(RECLAIM_INTERVAL);    while(1){        addrlen = sizeof(client_addr);        ret = recvfrom(sock,buf,MSGLEN,0,&client_addr,&addrlen);        if(ret!=-1){            buf[ret]='\0';            narrate("GOT:",buf,&client_addr);            //当在调用alarm()前已经设置了一个闹钟,那么我们可以调用alarm(0)来取消此闹钟,并返回剩余时间。            time_left = alarm(0);            handle_request(buf,&client_addr,addrlen);            alarm(time_left);        }else if(errno!=EINTR) perror("recvfrom");    }    return 0;}

lsrv_funcs2.c

/**********************************************************    > File Name: lsrv_funcs2.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月18日 星期三 14时27分17秒 ***********************************************************/#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<netdb.h>#include<signal.h>#include<sys/errno.h>#include<string.h>#include<unistd.h>#include<stdlib.h>#include<arpa/inet.h>#define RECLAIM_INTERVAL 60#define SERVER_PORTNUM 2020#define MSGLEN 128#define TICKET_AVAIL 0#define MAXUSERS 3#define oops(x) {perror(x);exit(-1);}int ticket_array[MAXUSERS];int sd = -1;int num_tickets_out = 0;char *do_hello();char *do_goodbye();void free_all_tickets(){    int i;    for(i=0;i<MAXUSERS;++i){        ticket_array[i]=TICKET_AVAIL;    }}void shut_down(){    close(sd);}void narrate(char *msg1,char *msg2,struct sockaddr_in *clientp){    fprintf(stderr,"\t\tSERVER:%s %s",msg1,msg2);    if(clientp)        fprintf(stderr,"(%s:%d)",inet_ntoa(clientp->sin_addr),ntohs(clientp->sin_port));    putc('\n',stderr);}//添加计时器处理,防止客户端断开失去连接,没有返回票的情况void ticket_reclaim(){    int i;    char tick[BUFSIZ];    for(i=0;i<MAXUSERS;++i){        if((ticket_array[i]!=TICKET_AVAIL)&&(kill(ticket_array[i],0)==-1)&&(errno==ESRCH)){            sprintf(tick,"%d.%d",ticket_array[i],i);            narrate("freeing",tick,NULL);            ticket_array[i]=TICKET_AVAIL;            num_tickets_out--;        }    }    alarm(RECLAIM_INTERVAL);}char *do_hello(char *msg_p){    int x;    static char replybuf[MSGLEN];    if(num_tickets_out>=MAXUSERS) return "FAIL no tickets available";    for(x=0;x<MAXUSERS&&ticket_array[x]!=TICKET_AVAIL;++x);    if(x==MAXUSERS){        narrate("database corrupt","",NULL);        return "FAIL database corupt";    }    ticket_array[x] = atoi(msg_p+5);    sprintf(replybuf,"TICK %d.%d",ticket_array[x],x);    num_tickets_out++;    return replybuf;}char *do_goodbye(char *msg_p){    int pid,slot;    if((sscanf((msg_p+5),"%d.%d",&pid,&slot)!=2)||            (ticket_array[slot]!=pid)){        narrate("Bogus ticket",msg_p+5,NULL);        return "FAIL invalid ticket";    }    ticket_array[slot] = TICKET_AVAIL;    num_tickets_out--;    return "THNX See ya!";}static char *do_validate(char *msg){    int pid,slot;    if(sscanf(msg+5,"%d.%d",&pid,&slot)==2&&ticket_array[slot]==pid) return "GOOD Valid ticket";    narrate("Bogus ticket",msg+5,NULL);    return "FAIL invalid ticket";}void handle_request(char *req,struct sockaddr_in *client,socklen_t addlen){    char *response;    int ret;    if(strncmp(req,"HELO",4)==0) response = do_hello(req);    else if(strncmp(req,"GBYE",4)==0) response = do_goodbye(req);    else if(strncmp(req,"VALD",4)==0) response = do_validate(req);    else response = "FAIL invalid request";    narrate("SAID:",response,client);    ret = sendto(sd,response,strlen(response),0,client,addlen);    if(ret==-1) perror("SERVER sendto failed");}int setup(){    sd = make_dgram_server_socket(SERVER_PORTNUM);    if(sd==-1) oops("make socket");    free_all_tickets();    return sd;}

logfiled.c

/**********************************************************    > File Name: logfiled.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月19日 星期四 11时40分50秒 ********************************************************/#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/un.h>#include<time.h>#include<string.h>#include<unistd.h>#include<stdlib.h>#define MSGLEN 512#define oops(m,x) {perror(m);exit(x);}#define SOCKNAME "/tmp/logfilesock"//使用Unix域的socket地址,只有同一台主机上的客户才能发消息给它int main(){    int sock;    struct sockaddr_un addr;    socklen_t addrlen;    char msg[MSGLEN];    int l;    char sockname[]=SOCKNAME;    time_t now;    int msgnum = 0;    char *timestr;    addr.sun_family = AF_UNIX;    strcpy(addr.sun_path,sockname);    addrlen = strlen(sockname)+sizeof(addr.sun_family);    sock = socket(PF_UNIX,SOCK_DGRAM,0);    if(sock==-1) oops("socket",2);    if(bind(sock,(struct sockaddr*)&addr,addrlen)==-1) oops("bind",3);    while(1){        l = read(sock,msg,MSGLEN);        msg[l] = '\0';        time(&now);        timestr = ctime(&now);        timestr[strlen(timestr)-1]='\0';        printf("[%5d]%s %s\n",msgnum++,timestr,msg);        fflush(stdout);    }    return 0;}

logfilec.c

/******************************************************    > File Name: logfilec.c    > Author: Duke-wei    > Mail: 13540639584@163.com     > Created Time: 2017年10月19日 星期四 11时49分16秒 ******************************************************/#include<stdio.h>#include<sys/types.h>#include<sys/socket.h>#include<sys/un.h>#include<stdlib.h>#include<unistd.h>#include<string.h>#define SOCKET "/tmp/logfilesock"#define oops(m,x) {perror(m);exit(x);}int main(int ac,char *av[]){    int sock;    struct sockaddr_un addr;    socklen_t addrlen;    char sockname[]=SOCKET;    char *msg = av[1];    if(ac!=2){        fprintf(stderr,"usage:logfilec 'message'\n");        exit(1);    }    sock = socket(PF_UNIX,SOCK_DGRAM,0);    if(sock==-1) oops("socket",2);    addr.sun_family = AF_UNIX;    strcpy(addr.sun_path,sockname);    addrlen = strlen(sockname)+sizeof(addr.sun_family);    if(sendto(sock,msg,strlen(msg),0,&addr,addrlen)==-1) oops("sendto",3);    return 0;}
原创粉丝点击