2019-2020-1 20175302 20175314 20175316 实验三 并发程序

2019-2020-1 20175302 201752314 20175316 实验三 并发程序

实验三 并发程序-1

实验内容

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

设计实现

  • 命令参数
    -c:统计字节数
    -l:统计行数
    -m:统计字符数。这个标志不能与 -c 标志一块儿使用。
    -w:统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串
    -L:打印最长行的长度
    -help:显示帮助信息
    --version:显示版本信息
    linux

  • 实现伪代码
    int main() { fd = fopen()//打开文件; fscanf()//对文件的内容以字符串的形式进行读取 if..count++//设置条件,当知足字符串条件时计数; }
    对于wc -w功能与咱们统计单词个数类似,而其实现时:由' ','\n','\t','\r'做为分隔符
    统计单词个数时,除上述分隔符,还加入了文本文件中常见的符号:'!','"','?','.',',','(',')',':',';','-'做为分隔符算法

  • 实现wc -w
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFERSIZE 1024

int main()
{
    FILE *fp;
    char ch;
    char filename[100];
    int flag=0,num=0;
        printf("input filename: ");
    scanf("%s",filename);
    if((fp = fopen(filename,"r"))==NULL)
    {
        printf("Failure to open %s\n",filename);
        exit(0);
    }
    while((ch=fgetc(fp))!=EOF)
    {
        if(ch==' ' || ch=='\n' || ch=='\t' || ch=='\r')
        {
            flag=0;
        }
        else
        {
            if(flag==0)
            {
                flag=1;
                num++;
            }

        }

    }
    printf("%c\n",num+48);
    fclose(fp);
    return 0;
}
  • wc txt
    安全

  • 实现单词个数统计
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFFERSIZE 1024
/*int num=0;
void wc(char buffer[],int size)
{
    int i,flag=0;
    for(i=0;i<size;i++)
    {
        if(buffer[i]==' ' || buffer[i]=='\n' || buffer[i]=='\t' || buffer[i]=='\0' || buffer[i]=='!' || buffer[i]=='?' || buffer[i]=='"' || buffer[i]=='.' || buffer[i]== ',' || buffer[i]==':' || buffer[i]=='(' || buffer[i]==')' || buffer[i]==';' || buffer[i]=='■ ' || buffer[i]=='•' )
        {
            flag=0;
        }
        else
        {
            if(flag==0)
            {
                num++;
            }
            flag=1;
        }
    }
    return num;
}*/
int main()
{
    FILE *fp;
    char ch;
    char filename[100];
    int flag=0,num=0;
        printf("input filename: ");
    scanf("%s",filename);
    if((fp = fopen(filename,"r"))==NULL)
    {
        printf("Failure to open %s\n",filename);
        exit(0);
    }
    while((ch=fgetc(fp))!=EOF)
    {
        if(ch==' ' || ch=='\n' || ch=='\t' ||  ch=='\!' || ch=='\?' || ch=='\"' || ch=='\.' || ch== '\,' || ch=='\:' || ch=='\(' || ch=='\)'     || ch=='\;' || ch=='\-')
        {
            flag=0;
        }
        else
        {
            if(flag==0)
            {
                flag=1;
                num++;
            }

        }

    }
    printf("%d\n",num);
    fclose(fp);
    return 0;
}
  • 客户端和服务器的通讯过程
    服务器

  • 运行结果
    网络

实验三 并发程序-2

实验内容

使用多线程实现wc服务器并使用同步互斥机制保证计数正确;
对比单线程版本的性能,并分析缘由。数据结构

多线程

  • 同步
    直接制约关系
    加入同步机制主要是为了在多线程程序中,若是须要对某个共享资源C进行同步访问,若是系统没有调度到B,A也是没有可能访问C的,必须等B调度到以后,A才可能从新访问。多线程

  • 互斥锁
    主要用来保护临界资源
    临界资源,就是有可能多个线程都须要访问的数据地址,也有多是某一段代码,执行这段代码有可能会改变多个线程都须要访问的数据。并发

  • 多线程实现wc服务器时,会出现多个客户端同时像服务器传送文件的状况,须要根据发送的不一样文件名建立新的接收文件,并要确立好调度顺序关系高并发

运行截图

  • 对比单线程版本的性能,并分析缘由
  • 缘由:全部数据结构的生存期,以及对这些数据结构的access,都用这一根逻辑线程,不须要考虑数据结构的race。把任何耗时的操做都给其余线程(IO线程、定时器线程,DB线程等)作,作完以后向事件队列(多线程安全的队列,其余线程是生产者,逻辑线程是消费者)丢事件。
  • 多线程逻辑设计的思路:
    全部数据结构的生存期,以及对这些数据结构的access,不必定在一根线程。
    须要考虑数据结构的race。
    网络事件、定时器事件唤醒工做线程(通常经过iocp或者epoll来唤醒)执行全部工做,通常不须要交换到其余线程。很显然,单线程逻辑多了一层事件队列交换,会增长延迟,以及全部的逻辑都在一根线程上跑,逻辑被阻塞也会带来延迟。其实吞吐量对于rpc来讲,是个宏观的概念,尽量快地消费网络消息就会提高吞吐量。
    对于高并发的程序,是没法忍受单线程逻辑。

实验三 并发程序-3

实验内容

  • 交叉编译多线程版本服务器并部署到实验箱中;
  • PC机做客户端测试wc服务器。

    实验步骤

    1.将实验箱与电脑相连,参照[实验一 开发环境的熟悉]的步骤操做,确保目标机(超级终端)和宿主机(虚拟机Ubuntu)能相互ping通(实验箱IP为192.168.0.232,Ubantu的IP为192.168.0.230)。

    2.修改客户端IP段代码。
    3.用交叉编译器arm-none-linux-gnuenbi-gcc编译server.c

    4.参照[实验一 开发环境的熟悉],挂载共享目录,经过NFS把宿主机中的程序运行目录映射到目标机中。
    5.在超级终端运行服务器armserve,在Ubantu运行客户端。

实验中遇到的问题和解决方案

  • 问题一:编译SM2的C文件时出现找不到库的问题。
  • 解决方案:输入两条命令重装
sudo apt-get remove openssl libssl-dev
sudo apt-get install openssl libssl-dev -y
  • 问题二:LED与UART代码编译不经过
  • 解决方案:将实验箱接入电源,链接实验箱与电脑,打开Z32下载调试工具软件资料\Z32下载调试工具\NZDownloadTool.exe,打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32便可被电脑识别,显示1设备已链接后,点击浏览,选择\实验 1-LED 闪烁\bin\Z32HUA.bin,点击下载,绿色进度条加载完成后,程序下载成功

实验心得与体会

  • 本次实验利用uVision4破解MDK,经过串口助手实现试验箱Z32和电脑之间的数据传输和通讯,学会了如何下载程序到试验箱和我国的密算法标准SM1,SM2,SM3,SM4,实验较为简单,但须要调试软件,须要耐心。

  • SM1:对应密码学分组密码算法,普遍应用于电子政务、电子商务及国民经济的各个应用领域(包括国家政 务通、警务通等重要领域)。

  • SM2:对应密码学公钥密码算法RSA,用于加解密及数字签名。

  • SM3:对应密码学摘要算法MD5,适用于商用密码应用中的数字签名和验证。

  • SM4:对应密码学分组密码算法DES,用于无限局域网产品使用。

参考资料

相关文章
相关标签/搜索