zoukankan      html  css  js  c++  java
  • 2019-2020-1 20175209王梓鸿 实验三 并发程序

    实验三 并发程序

    实验三-并发程序-1

    实验内容:

    • 1.学习使用Linux命令wc(1)。

    • 2.基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端。

      • 客户端传一个文本文件给服务器。

      • 服务器返加文本文件中的单词数。

    实验步骤:

    • 学习使用Linux命令wc

      • 首先,我们使用man -k wc查看wc命令的系统调用:

      • 接下来用man 1 wc 查看wc指令:

    • wc指令功能:统计指定文件中的字节数、字数、行数,并将统计结果显示输出。

    • wc指令格式:wc [选项] 文件...

    • wc指令描述:其中word字长是由空格分隔的非零长度序列。

    • wc命令参数:

      • -c 统计字节数。

      • -l 统计行数。

      • -m 统计字符数。这个标志不能与 -c 标志一起使用。

      • -w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。

      • -L 打印最长行的长度。

    • 可以使用wc -w命令统计字数,但是字的定义是“空白、跳格或换行字符分隔的字符串”,和单词数不完全相同

    服务器端与客户端实现代码

    • 服务器端
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    #define MYPORT 175209
    
    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);
    }
    
    • 客户端
    #include <stdio.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include <string.h>
    
    #define MYPORT 175209
    
    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

    实验内容:

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

    • 对比单线程版本的性能,并分析原因。

    实验步骤:

    • 在开始前,需要了解一下同步和互斥的区别:

      • 1.互斥是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

      • 2.同步是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。

      • 3.同步其实已经实现了互斥,所以同步是一种更为复杂的互斥。

      • 4.互斥是一种特殊的同步。

    • 所以服务器代码需要增加两个功能:

      • 增加多线程。

      • 使用同步互斥。

    服务器端与客户端实现代码

    • 服务器端
    #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 175209
    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);
    }
    
    • 客户端
    #include <stdio.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include <string.h>
    
    #define MYPORT 175209
    
    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);
    }
    
    • 运行结果

    • 需要注意的是
      因为pthread库不是Linux系统默认的库,连接时需要使用库libpthread.a,所以在使用pthread_create创建线程时,在编译中要加-lpthread参数:gcc server.c -lpthread -o server 加上这个以后编译成功!

    • 单线程与多线程的区别:

      • 单线程程序:只有一个线程,代码顺序执行,容易出现代码阻塞(页面假死)。

      • 多线程程序:有多个线程,线程间独立运行,能有效地避免代码阻塞,并且提高程序的运行性能。

    • 单线程与多线程的优缺点分析:

      • 多线程优缺点:同步应用程序的开发比较容易,但由于需要在上一个任务完成后才能开始新的任务,所以其效率通常比多线程应用程序低。如果完成同步任务所用的时间比预计时间长,应用程序可能会不响应。多线程处理可以同时运行多个过程。

      • 单线程优缺点:单线程的也就是程序执行时,所跑的程序路径(处理的东西)是连续顺序下来的,必须前面的处理好,后面的才会执行到。

    实验三-并发程序-3

    实验内容:

    • 交叉编译多线程版本服务器并部署到实验箱中。

    • PC机作客户端测试wc服务器。

    • 提交测试截图。

    实验步骤:

    • 在超级终端中用“mkdir /arm_20175209”建立实验箱中程序运行目录“arm_20175209”;

    • 在超级终端中运行“mount -t nfs -o nolock 宿主机IP:/home/wzh/20175209/信息安全系统/wzh/Experiment3/Server2 /arm_20175209”通过NFS把宿主机中的“Server2” 映射到目标机中的“/arm_20175209”

    • 超级终端中运行"cd /arm_20175209"

    • 超级终端中运行"./armServer2", 提交运行截图,并深入理解交叉编译

    • 运行截图

    学习到的知识点:

    • 了解了多线程的优点:多线程技术使程序的响应速度更快 ,因为用户界面可以在进行其它工作的同时一直处于活动状态。有多个线程,线程间独立运行,能有效地避免代码阻塞,并且提高程序的运行性能。
  • 相关阅读:
    .NETCORE CONSUL
    Jenkins+github自动化部署.Net Core程序到Docker
    CleanArchitecture原则CQRS模式
    BFF架构了解
    .NET 生态系统的蜕变之 .NET 6
    Deislabs开源 使用WebAssembly打造的PaaS项目Hippo
    微软认真聆听了开源 .NET 开发社区的炮轰: 通过CLI 支持 Hot Reload 功能
    单体应用 适合采用 dapr 构建吗?
    微软发布了Visual Studio 2022 RC版,并将在11月8日发布正式版
    [LeetCode] 1248. Count Number of Nice Subarrays 统计优美子数组
  • 原文地址:https://www.cnblogs.com/wangzihong0213/p/11889594.html
Copyright © 2011-2022 走看看