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

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

    实验小组成员 20175202葛旭阳 20175204张湲祯 20175216张雪原

    《信息安全系统设计基础》实验三【并发程序】

    实验小组成员:20175202 葛旭阳 20175204 张湲祯 20175216 张雪原

    任务一【并发程序-1】

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

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

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

    2.在虚拟机中同时打开两个终端,一个作为客户端,一个作为服务器端;
    3.将文件test1.txt和文件test2.txt复制到虚拟机中;
    4.编译并运行客户端和服务器端代码;
    5.首先运行服务器端代码,连接到服务器;
    6.运行客户端代码,发送请求;
    7.输入要请求的.txt文件名。
    8.服务器端代码如下:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    #define MYPORT 175202
    
    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("accept client %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);
    }
    

    9.客户端代码如下:

    #include <stdio.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include <string.h>
    
    #define MYPORT 175202
    
    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];
        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);
    }
    

    二、实验结果截图:

    任务二 【并发程序-2】

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

    二、实验步骤:
    1.在虚拟机中同时打开两个终端,一个作为客户端,一个作为服务器端;
    2.将文件test1.txt和文件test2.txt复制到虚拟机中;
    3.编译并运行客户端和服务器端代码;
    4.首先运行服务器端代码,连接到服务器;
    5.运行客户端代码,发送请求;
    6.输入要请求的.txt文件名;
    7.服务器端代码如下:

    #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 165318
    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("accept client %s
    ", inet_ntoa(remote_addr.sin_addr));
            pthread_create(&t, NULL, &wc, NULL);
            pthread_join(&t, NULL);
        }
        close(serverfd);
    }
    

    8.客户端代码如下:

    #include <stdio.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include <string.h>
    
    #define MYPORT 165318
    
    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];
        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);
    }
    

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

    三、实验结果截图:

    任务三 【并发程序-3】

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

    二、实验步骤:
    1.参考实验1在Ubuntu中对服务器代码交叉编译。
    2.将实验箱与电脑连接好,配置好网络模式并能ping通;
    3.打开虚拟机命令行终端,配置/etc/exports
    sudo vim /etc/exports
    NFS允许挂载的目录及权限在文件/etc/exports中进行了定义。需要把/home/linux/sy3目录共享出来,那么我们只需要在/etc/exports文件末添加如下一行:
    /home/linux/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/sy3
    5.最后运行程序。

    三、实验结果截图:

    实验总结

    本次实验首先遇到了很多问题:一、在做实验二时,编译服务器端的代码不通过,出现如下问题;
    后来发现原因是pthread库不是Linux系统默认的库,优先使用gcc createThread.c -lpthread -o createThread,随后再使用gcc编译,解决了问题。
    二、再做实验三时,实验箱和电脑ping不通,无法完成部署;


    后发现是因为重启虚拟机后没有把网络配置改成桥接所致,修改后,成功ping通。
    三、在运行多线程时,无法打开多个客户端。因为在分配给Ubuntu虚拟机时只分配一个单核处理器,改为多个处理器多核就可以正常运行。

    在本次实验让我更加熟悉了实验箱的运用和操作步骤,也对socket编程从只有浅显理论知识上升到了实践层面,对单线程和多线程运行有了更直观的认识与了解,之后的两次实验我也会像这样一样认真对待,争取有更大的收获!

  • 相关阅读:
    设计模式之原型模式
    Mac OSx下的APK反编译
    Android中ListView封装收缩与展开
    带密码登录的密码保险箱应用源码
    HTML 5缓存机制:Cache Manifest配置实例
    PHP开发大型项目的一点经验
    Windows Phone 编程: 摇一摇 效果
    swift皮筋弹动发射飞机
    Win8.1应用开发之适配器模式(C#实现)
    java实现身份证校验
  • 原文地址:https://www.cnblogs.com/gexvyang/p/11881837.html
Copyright © 2011-2022 走看看