zoukankan      html  css  js  c++  java
  • 2019-2020-1 20175204 20175202 20175216 《信息安全系统设计基础》实验三 并发程序

    2019-2020-1 20175204 20175202 20175216 《信息安全系统设计基础》实验三 并发程序

    组员 20175204 张湲祯 20175202 葛旭阳 20175216 张雪原

    任务一【并发程序-1】

    一、实验任务:
    1.学习使用Linux命令wc(1)
    2.基于Linux套接字程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
    3.客户端传一个文本文件给服务器
    4.服务器返回加文本文件中的单词数个以上

    5.提交代码
    附件提交测试截图,至少要测试附件中的两个文件

    二、实验步骤:
    1.学习使用man wc命令;

    wc指令功能:统计指定文件中的字节数、字数、行数,并将统计结果显示输出。
    wc指令格式:wc [选项] 文件...
    wc指令描述:其中word字长是由空格分隔的非零长度序列。
    wc命令参数:
    -c 统计字节数。
    -l 统计行数。
    -m 统计字符数。这个标志不能与 -c 标志一起使用。(字的定义是“空白、跳格或换行字符分隔的字符串”,和单词数不完全相同)
    -w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。
    -L 打印最长行的长度。
    2.wc命令的使用:

    3.服务器代码:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    #define MYPORT 175204
    
    void main(){
       int serverfd, clientfd;
       struct sockaddr_in my_addr;
       struct sockaddr_in remote_addr;
    
       char buffer[BUFSIZ];
       memset(&my_addr, 0, sizeof(my_addr));
       my_addr.sin_family=AF_INET;
       my_addr.sin_addr.s_addr=INADDR_ANY;
       my_addr.sin_port=htons(MYPORT);
    
       if((serverfd=socket(PF_INET, SOCK_STREAM, 0))==-1){
           perror("socket");
       }
       
       if(bind(serverfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))<0){
           perror("bind");
       }
       listen(serverfd, 5);
       int addrlen=sizeof(struct sockaddr_in);
       while(1){
           if((clientfd=accept(serverfd, (struct sockaddr *)&remote_addr, &addrlen))<0){
               perror("accept");
       }
       printf("接收到客户端 %s
    ", inet_ntoa(remote_addr.sin_addr));
       int len, i;
       long wordscount=0;
       int flag=1;
       while(1){
           if((len=recv(clientfd, buffer, 1024, 0))>0){
               for(i=0; i<len; i++){
                   if(flag==0){
                       switch(buffer[i]){
                           case ' ':
                               wordscount++;
                               break;
                           case '
    ':
                               wordscount++;
                               break;
                           case '
    ':
                               wordscount++;
                               break;
                           default:
                               break;
                       }
                   }
               if(buffer[i]== ' ' || buffer[i]=='
    ' || buffer[i]=='
    ') flag=1;
               else flag=0;
               }
           }
           if(len<1024) break;
       }
       send(clientfd, &wordscount, sizeof(long), 0);
       close(clientfd);
       }
       close(serverfd);
    
    

    4.客户端代码:

    #include <stdio.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include <string.h>
    
    #define MYPORT 175204
    
    void main(){
       int clientfd;
       struct sockaddr_in remote_addr;
       char buffer[BUFSIZ];
       memset(&remote_addr, 0 , sizeof(remote_addr));
       remote_addr.sin_family=AF_INET;
       remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
       remote_addr.sin_port=htons(MYPORT);
    
       if((clientfd=socket(PF_INET,SOCK_STREAM,0))<0){  
           perror("socket");  
       }
    
       if(connect(clientfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr))<0){
           perror("connect");
       }
    
       int len;
       FILE *fp;
       char path[20];
    printf("请输入需要测试的文件名");
       gets(path);
    
       fp=fopen(path, "r");
       char readch;
       int i=0;
       while((readch=fgetc(fp))!=EOF){
           if(i<1024){
               buffer[i]=readch;
               i++;
           }
           else{
               i=0;
               int n=send(clientfd, buffer, 1024, 0);
           }
       }
       fclose(fp);
       if(i!=0)
           send(clientfd, buffer, i, 0);
       long wordscount;
       recv(clientfd, &wordscount, sizeof(long), 0);
       printf("%ld
    ", wordscount);
       close(clientfd);
    }
    
    

    5.分别打开两个终端,对服务器代码sever.c和客户端代码client.c分别编译;后在两个终端分别运行;先运行服务器在运行客户端,后根据要求输入需要测试的文件名,进行测试。

    任务二 【并发程序-2】

    一、实验任务:
    1.使用多线程实现wc服务器并使用同步互斥机制保证计数正确
    2.上方提交代码
    3.下方提交测试
    4.对比单线程版本的性能,并分析原因
    二、实验步骤:
    1.重新编写并编译运行服务器代码;
    2.服务器代码:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    #include <pthread.h>
    
    #define MYPORT 175204
    pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
    int serverfd, clientfd;
    char buffer[BUFSIZ];
    
    void *wc(void *m){
       pthread_mutex_lock( &counter_mutex );
       int len, i;
       long wordscount=0;
       int flag=1;
       while(1){
           if((len=recv(clientfd, buffer, 1024, 0))>0){
               for(i=0; i<len; i++){
                   if(flag==0){
                       switch(buffer[i]){
                           case ' ':
                               wordscount++;
                               break;
                           case '
    ':
                               wordscount++;
                               break;
                           case '
    ':
                               wordscount++;
                               break;
                           default:
                               break;
                       }
                   }
                   if(buffer[i]== ' ' || buffer[i]=='
    ' || buffer[i]=='
    ')
                       flag=1;
                   else
                       flag=0;
               }
           }
           if(len<1024)
               break;
       }
       send(clientfd, &wordscount, sizeof(long), 0);
       close(clientfd);
       pthread_mutex_unlock( &counter_mutex );
       return NULL;
    }
    void main(){
       pthread_t t;
       char arg[30];
    
       struct sockaddr_in my_addr;
       struct sockaddr_in remote_addr;
    
       memset(&my_addr, 0, sizeof(my_addr));
       my_addr.sin_family=AF_INET;
       my_addr.sin_addr.s_addr=INADDR_ANY;
       my_addr.sin_port=htons(MYPORT);
    
       if((serverfd=socket(PF_INET, SOCK_STREAM, 0))==-1){
           perror("socket");
       }
    
       if(bind(serverfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))<0){
           perror("bind");
       }
       listen(serverfd, 5);
       int addrlen=sizeof(struct sockaddr_in);
       while(1){
           if((clientfd=accept(serverfd, (struct sockaddr *)&remote_addr, &addrlen))<0){
               perror("accept");
           }
           printf("接收到客户端 %s
    ", inet_ntoa(remote_addr.sin_addr));
           pthread_create(&t, NULL, &wc, NULL);
           pthread_join(&t, NULL);
       }
       close(serverfd);
    }
    

    3.客户端代码:

    #include <stdio.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include <string.h>
    
    #define MYPORT 175204
    
    void main(){
       int clientfd;
       struct sockaddr_in remote_addr;
       char buffer[BUFSIZ];
       memset(&remote_addr, 0 , sizeof(remote_addr));
       remote_addr.sin_family=AF_INET;
       remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
       remote_addr.sin_port=htons(MYPORT);
    
       if((clientfd=socket(PF_INET,SOCK_STREAM,0))<0){  
           perror("socket");  
       }
    
       if(connect(clientfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr))<0){
           perror("connect");
       }
    
       int len;
       FILE *fp;
       char path[20];
    printf("请输入需要测试的文件名:");
       gets(path);
       fp=fopen(path, "r");
       char readch;
       int i=0;
       while((readch=fgetc(fp))!=EOF){
           if(i<1024){
               buffer[i]=readch;
               i++;
           }
           else{
               i=0;
               int n=send(clientfd, buffer, 1024, 0);
           }
       }
       fclose(fp);
       if(i!=0)
           send(clientfd, buffer, i, 0);
       long wordscount;
       recv(clientfd, &wordscount, sizeof(long), 0);
       printf("%ld
    ", wordscount);
       close(clientfd);
    }
    

    4.分别打开多个终端,一个终端运行服务器,其余终端运行客户端;
    运行多个客户端后,服务端会收到多个请求。


    5.对比单线程的版本的性能,并分析原因。
    单线程容易实现,但是一次只允许一个客户端连接。
    多线程更复杂,但是一次允许多个客户端,工作效率更高。
    单线程保证单用户的安全性,但多线程保证任务的高效性。

    任务三 【并发程序-3】

    一、实验任务:
    1.交叉编译多线程版本服务器并部署到实验箱中
    2.PC机作客户端测试wc服务器
    3.提交测试截图

    二、实验步骤:
    1.参考实验1在Ubuntu中对服务器代码交叉编译。
    2.将实验箱与电脑连接好,配置好网络模式并能ping通;
    3.打开虚拟机命令行终端,配置/etc/exports;
    sudo vim /etc/exports
    NFS允许挂载的目录及权限在文件/etc/exports中进行了定义。需要把/home/linux/175204zyz/sy3目录共享出来,那么我们只需要在/etc/exports文件末添加如下一行:
    /home/linux/175204zyz/sy3 *(rw,sync,no_root_squash,no_subtree_check)
    保存并推出,随后重启服务:
    sudo /etc/init.d/nfs-kernel-server restart
    4.在超级终端中mount -t nfs -o nolock 192.168.0.230(宿主机IP):/home/linux/175204zyz/sy3
    5.然后运行程序。

    实验总结

    本次实验我们小组首先遇到了很多问题:
    问题1:在任务二中编译服务器代码时出现致命错误。

    解决方案:通过参考对pthread_create未定义的引用,因为pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时,命令使用gcc server.c -lpthread -o createThread.
    问题2:运行多线程时,打开多个客户端输入直接卡死。
    解决方案:由于在分配给Ubuntu虚拟机时只分配一个单核处理器,改为多个处理器多核就可以正常运行。

    在本次实验中也回顾了第一次实验对实验箱的运用操作,还对socket编程有了进一步的理解与学习,对单线程和多线程运行有了更直观的认识与了解,感觉自己还需要努力学习。

  • 相关阅读:
    2020.5.28.第十三周java上机练习
    2020.5.22第十二周java作业
    2020.5.21.第十二周java上机练习
    2020.5.15.java第十一周作业
    2020.5.14.第十一周上机练习
    leetcode02大数相加
    leetcode算法题01
    近期wxss总结
    近期Freecodecamp问题总结
    freecodecamp数字转化成罗马数字
  • 原文地址:https://www.cnblogs.com/zyzgl/p/11882321.html
Copyright © 2011-2022 走看看