• 2017-2018-1 20155209 实验三 实时系统


    2017-2018-1 20155209 实验三 实时系统

    学习使用Linux命令wc(1)

    基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
    客户端传一个文本文件给服务器
    服务器返加文本文件中的单词数

    • 使用man 1 wc查看wc
    • 代码实现如下:
    • 客户端
    #include <stdio.h>
    #include <netinet/in.h>                                                                   
    #include <arpa/inet.h>
    #include <netdb.h>    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define RIO_BUFSIZE 8192
    
    typedef struct{
        int rio_fd;
        int rio_cnt;
        char *rio_bufptr;
        char rio_buf[RIO_BUFSIZE];
    
    }rio_t;
    
    #define MAXLINE 200
    
    int main(int argc,char **argv){
    
        int clientfd,port;
        char *host,buf[MAXLINE];
        char sbuf[MAXLINE];
        char rbuf[MAXLINE];
        rio_t rio;
        char str1[MAXLINE]="客户端IP:";
        char str2[MAXLINE]="服务器实现者学号:20155209”;
        
        char str3[MAXLINE]="当地时间:";
    
        FILE *fp;
    
        char filename[MAXLINE];
    
    
        if(argc!=3){
        
            fprintf(stderr,"usage:%s <host> <port>
    ",argv[0]);
            exit(0);
        }
        host = argv[1];
        port = atoi(argv[2]);
    
        clientfd = open_clientfd(host,port);
      
        while(1){
    
            printf("输入文件名(.txt):
    ");
    
            gets(filename);
    
            fp = fopen(filename,"rb");
    
            while(!feof(fp)){
    
            fgets(sbuf,MAXLINE,fp);
            
            send(clientfd,sbuf,MAXLINE,0);
    
            bzero(sbuf,sizeof(sbuf));       
            }
           
    
            printf("%s",str1);
            puts(host);
    
            printf("%s",str2);
            putchar('
    ');
    
            //printf("%s",str3);
          
            //puts(rbuf);
    
            fclose(fp);
    
            //sleep(1000);
    
            //recv(clientfd,rbuf,MAXLINE,0);
    
            //printf("传输完成,该文件单词数为%s
    !",rbuf);
    
            //puts(rbuf);
    
            close(clientfd);
           
            exit(0);
        }
    
    }
    
    
    
    • 服务器
    
    #include <stdio.h>
    #include <unistd.h>
    #include <netinet/in.h>                                                                   
    #include <arpa/inet.h>
    #include <netdb.h>    
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    
    #define MAXLINE 200
    #define RIO_BUFSIZE 8192
    
    typedef struct{
        int rio_fd;
        int rio_cnt;
        char *rio_bufptr;
        char rio_buf[RIO_BUFSIZE];
    
    }rio_t;
    
    typedef struct sockaddr SA;
    
    typedef struct{
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
    int tm_wday;
    int tm_yday;
    int tm_isdst;
    }tm;
    
    void sigchld_handler(int sig){
    
        pid_t pid;
        int stat;
    
        while((pid = waitpid(-1,&stat,WNOHANG))>0){
            printf("child %d terminated
    ",pid);
        }
        return;
    }
    
    void itoa (int n,char s[])
    {
        int i,j,sign;
        char temp[MAXLINE];
    
        if((sign=n)<0)//记录符号
            n=-n;//使n成为正数
        i=0;
        do{
                   temp[i++]=n%10+'0';//取下一个数字
        }
        while ((n/=10)>0);//删除该数字
        if(sign<0)
            temp[i++]='-';
    
        for(j=0;j<i;j++){//生成的数字是逆序的,所以要逆序输出
            s[j] = temp[i-j-1];
        }
        s[i] = '';
    } 
    
    int main(int argc,char **argv){
    
        int count=0,cnt=0,listenfd,connfd,port,clientlen;
        struct sockaddr_in clientaddr;
        struct hostent *hp;
        char *haddrp;
        char sbuf[MAXLINE];
       // char *bufp = sbuf;
        char rbuf[MAXLINE];
        rio_t rio;
        time_t lt;
        tm *local;
        char str1[MAXLINE]="客户端IP:";
        char str2[MAXLINE]="服务器实现者学号:";
        char str3[MAXLINE]="当地时间:";
    
        FILE *fp = fopen("test.txt","wb");
    
        if(argc != 2){
        
            fprintf(stderr,"usage:%s <port>
    ",argv[0]);
            exit(0);
        }
    
        port = atoi(argv[1]);
    
        signal(SIGCHLD,sigchld_handler);
        listenfd = open_listenfd(port);
        while(1){
        
            clientlen = sizeof(clientaddr);
            connfd = accept(listenfd,(SA *)&clientaddr,&clientlen);
    
            hp = gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
                    sizeof(clientaddr.sin_addr.s_addr),AF_INET);
            haddrp = inet_ntoa(clientaddr.sin_addr);
            printf("server connected to %s (%s)
    ",hp->h_name,haddrp);
    
            
            if(fork() == 0){
            close(listenfd);
            
    
            /*
            lt = time(NULL); 
            local = localtime(&lt);
            strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
            */
    
            while(cnt = recv(connfd,rbuf,MAXLINE,0)){
    
            //printf("%d
    ",recv(connfd,rbuf,MAXLINE,0));   
            fputs(rbuf,fp);
            bzero(rbuf,sizeof(rbuf));
    
            count += cnt;
            }
    
            //printf("传输成功!,该文件单词数共%d
    !",count);
    
            fclose(fp);
    
            itoa(count,sbuf);
    
            //send(connfd,sbuf,MAXLINE,0);
           
            printf("该文件单词数为%s!
    ",sbuf);
    
            close(connfd);
            exit(0);
            }
            
    
            close(connfd);
        }
    }
    
    
    • 实现截图:

    使用多线程实现wc服务器并使用同步互斥机制保证计数正确

    上方提交代码
    下方提交测试
    对比单线程版本的性能,并分析原因

    • 代码实现如下:
    • 客户端
    
    #include <stdio.h>
    #include <netinet/in.h>                                                                   
    #include <arpa/inet.h>
    #include <netdb.h>    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define RIO_BUFSIZE 8192
    
    typedef struct{
        int rio_fd;
        int rio_cnt;
        char *rio_bufptr;
        char rio_buf[RIO_BUFSIZE];
    
    }rio_t;
    
    #define MAXLINE 200
    
    int main(int argc,char **argv){
    
        int clientfd,port;
        char *host,buf[MAXLINE];
        char sbuf[MAXLINE];
        char rbuf[MAXLINE];
        rio_t rio;
        char str1[MAXLINE]="客户端IP:";
        char str2[MAXLINE]="服务器实现者学号:20155209”;
        
        char str3[MAXLINE]="当地时间:";
    
        FILE *fp;
    
        char filename[MAXLINE];
    
    
        if(argc!=3){
        
            fprintf(stderr,"usage:%s <host> <port>
    ",argv[0]);
            exit(0);
        }
        host = argv[1];
        port = atoi(argv[2]);
    
        clientfd = open_clientfd(host,port);
      
        while(1){
    
            printf("输入文件名(.txt):
    ");
    
            gets(filename);
    
            fp = fopen(filename,"rb");
    
            while(!feof(fp)){
    
            fgets(sbuf,MAXLINE,fp);
            
            send(clientfd,sbuf,MAXLINE,0);
    
            bzero(sbuf,sizeof(sbuf));       
            }
           
    
            printf("%s",str1);
            puts(host);
    
            printf("%s",str2);
            putchar('
    ');
    
            //printf("%s",str3);
          
            //puts(rbuf);
    
            fclose(fp);
    
            //sleep(1000);
    
            //recv(clientfd,rbuf,MAXLINE,0);
    
            //printf("传输完成,该文件单词数为%s
    !",rbuf);
    
            //puts(rbuf);
    
            close(clientfd);
           
            exit(0);
        }
    
    }
    
    
    • 服务器
    #include <stdio.h>
    #include <unistd.h>
    #include <netinet/in.h>                                                                   
    #include <arpa/inet.h>
    #include <netdb.h>    
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdlib.h>
    #include <time.h>
    #include <string.h>
    #include <pthread.h>
    
    #define MAXLINE 200
    #define RIO_BUFSIZE 8192
    
    typedef struct{
        int rio_fd;
        int rio_cnt;
        char *rio_bufptr;
        char rio_buf[RIO_BUFSIZE];
    
    }rio_t;
    
    typedef struct sockaddr SA;
    
    typedef struct{
    int tm_sec;
    int tm_min;
    int tm_hour;
    int tm_mday;
    int tm_mon;
    int tm_year;
    int tm_wday;
    int tm_yday;
    int tm_isdst;
    }tm;
    
    
    
    void itoa (int n,char s[]);
    
    void *thread(void *vargp);
    
    int main(int argc,char **argv){
    
        int listenfd,*connfdp,port;
        int clientlen;
        struct sockaddr_in clientaddr;
        struct hostent *hp;
        char *haddrp;
        pthread_t tid;
    
        if(argc != 2){
        
            fprintf(stderr,"usage:%s <port>
    ",argv[0]);
            exit(0);
        }
    
        port = atoi(argv[1]);
    
        listenfd = open_listenfd(port);
        
        
        while(1){
        
            clientlen = sizeof(clientaddr);
    
            connfdp =malloc(sizeof(int));
        
            *connfdp = accept(listenfd,(SA *)&clientaddr,&clientlen);
    
    
            hp = gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
                    sizeof(clientaddr.sin_addr.s_addr),AF_INET);
    
            haddrp = inet_ntoa(clientaddr.sin_addr);
    
            printf("server connected to %s (%s)
    ",hp->h_name,haddrp);
    
            pthread_create(&tid,NULL,thread,connfdp);
    
            pthread_join(tid,NULL);
        }
    }
    
    
    void *thread(void *vargp){
        
        time_t lt;
        tm *local;
        char sbuf[MAXLINE];
        int cnt = 0,count = 0;
        char *fp = fopen("test.txt","wb");
        char rbuf[MAXLINE];
        int connfd = *((int*)vargp);
    
        free(vargp);
    
        pthread_detach(pthread_self());
    
        /*lt = time(NULL); 
        local = localtime(&lt);
        strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
        send(connfd,sbuf,MAXLINE,0);
        */
    while(cnt = recv(connfd,rbuf,MAXLINE,0)){
    
            //printf("%d
    ",recv(connfd,rbuf,MAXLINE,0));   
            fputs(rbuf,fp);
            bzero(rbuf,sizeof(rbuf));
    
            count += cnt;
            }
    
    
            //printf("传输成功!,该文件单词数共%d
    !",count);
    
            fclose(fp);
    
            itoa(count,sbuf);
    
            //send(connfd,sbuf,MAXLINE,0);
           
            printf("该文件单词数为%s!
    ",sbuf);
    
        close(connfd);
        
        return NULL;
    }
    
    
    void itoa (int n,char s[])
    {
        int i,j,sign;
        char temp[MAXLINE];
    
        if((sign=n)<0)//记录符号
            n=-n;//使n成为正数
        i=0;
        do{
                   temp[i++]=n%10+'0';//取下一个数字
        }
        while ((n/=10)>0);//删除该数字
        if(sign<0)
            temp[i++]='-';
    
        for(j=0;j<i;j++){//生成的数字是逆序的,所以要逆序输出
            s[j] = temp[i-j-1];
        }
        s[i] = '';
    } 
    
    
    • 程序运行结果截图:

    • 实验中遇到的问题:在自己电脑(Mac)运行代码出现如下问题:Static library link issue with Mac OS X: symbol(s) not found for architecture x86_64。

    • 解决方法:在网上寻找了许多方法都不能编译成功。最后在Mac里安装了Linux虚拟机,在虚拟机里做这个实验了。

  • 相关阅读:
    luoguP5162 WD与积木
    maven学习7 settings.xml解析
    mybatis 学习六 MyBatis主配置文件
    mybatis 学习五 动态SQL语句
    mybatis 学习四(下) SQL语句映射文件增删改查、参数、缓存
    mybatis 学习四 (上)resutlMap
    mybatis 学习三 关键文件解析
    spring 学习二 @RequestMapping
    Spring 学习一 @Autowired
    mybatis 学习二 MyBatis简介与配置MyBatis+Spring+MySql
  • 原文地址:https://www.cnblogs.com/lhyhahaha/p/7862818.html
Copyright © 2020-2023  润新知