zoukankan      html  css  js  c++  java
  • 2017-2018-1 20155214 《信息安全系统设计基础》实验三 并发程序

    2017-2018-1 20155214 《信息安全系统设计基础》

    实验三 并发程序

    实验要求

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

    任务二
    使用多线程实现wc服务器并使用同步互斥机制保证计数正确
    上方提交代码
    下方提交测试
    对比单线程版本的性能,并分析原因

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

    实验背景

    • wc
      统计指定文件中的字节数、字数、行数,并将统计结果显示输出。该命令统计指定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所指定文件的总统计数。

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

    伪代码

    //客户端
    ......
    打开文件
    while(文件不为空){
    将文件读入缓存区
    将缓冲区内容发送至服务器
    }
    
    接收服务器返回的字数
    ......
    
    //服务器
    ......
    打开文件
    while(当客户端传输字节不为0){
    调用wc函数计算接收缓存区中的字数
    将缓存区里的内容写入文件
    }
    
    将统计的文件字数返回给客户端
    ......
    

    多线程实现

    • 线程创建函数CreateThread(),属于API函数;
    HANDLE CreateThread(  
      LPSECURITY_ATTRIBUTES lpThreadAttributes, //指向结构体SECURITY_ATTRIBUTES的指针,表示指定新建线程的安全属性
      DWORD dwStackSize, //指定线程初始化时地址空间的大小
      LPTHREAD_START_ROUTINE lpStartAddress,//指定该线程的线程函数的地址   
      LPVOID lpParameter,//将要传递给新建线程的命令行参数                
      DWORD dwCreationFlags, //指定新建线程创建后是否立即执行                
      LPDWORD lpThreadId   ); 表示新建线程的ID号
    
    • pthread_create调用成功以后,新线程和老线程谁先执行,谁后执行用户是不知道的,这一块取决与操作系统对线程的调度,如果我们需要等待指定线程结束,需要使用pthread_join函数,这个函数实际上类似与多进程编程中的waitpid。

    • gcc编译时需要加上-lpthread,要不然会报错

    多线程的同步互斥

    • 通过信号量控制。信号量本质上是一个非负数的整数计数器,它也被用来控制对公共资源的访问。当公共资源增加的时候,调用信号量增加函数sem_post()对其进行增加,当公共资源减少的时候,调用函数sem_wait()来减少信号量。

    • 关键代码

    void *thread(void *vargp){
        
        time_t lt;
        tm *local;
        char sbuf[MAXLINE];
        int 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(recv(connfd,rbuf,MAXLINE,0)){
    
            //printf("%d
    ",recv(connfd,rbuf,MAXLINE,0));   
            fputs(rbuf,fp);
         
            count += wc(rbuf);
    
            bzero(rbuf,sizeof(rbuf));
            }
    
    
            //printf("传输成功!,该文件单词数共%d
    !",count);
    
            fclose(fp);
    
            itoa(count,sbuf);
    
            //send(connfd,sbuf,MAXLINE,0);
           
            printf("该文件单词数为%s!
    ",sbuf);
    
        close(connfd);
        
        return NULL;
    }
    
    

    多线程编程的目的,就是"最大限度地利用CPU资源",当某一线程的处理不需要占用CPU而只和I/O,OEMBIOS等资源打交道时,让需要占用CPU资源的其它线程有机会获得CPU资源。每个程序执行时都会产生一个进程,而每一个进程至少要有一个主线程。这个线程其实是进程执行的一条线索,除了主线程外你还可以给进程增加其它的线程,也即增加其它的执行线索,由此在某种程度上可以看成是给一个应用程序增加了多任务功能。当程序运行后,您可以根据各种条件挂起或运行这些线程,尤其在多CPU的环境中,这些线程是并发运行的。多线程就是在一个进程内有多个线程。从而使一个应用程序有了多任务的功能。

    • 通过命令行/usr/local/toolchain/toolchain4.3.2/bin/arm-none-linux-gnuenbi-gcc -c dateserveri.c /usr/local/toolchain/toolchain4.3.2/bin/arm-none-linux-gnuenbi-gcc -static -o dateserveri dateserveri.o csapp.a -lpthread即可实现交叉编译。
  • 相关阅读:
    Linux开机启动流程(centos7)
    系统平均负载
    Linux基础命令screen(后台管理程序)
    Linux基础命令nohup & (管理进程的后台)
    Linux基础命令kill(终止进程)
    Linux基础命令top(动态显示进程状态)
    Linux基础练习题答案7.31
    Linux基础命令ps
    Swap虚拟内存(内存满了怎么办?)
    50 | 深入浅出网站高可用架构设计
  • 原文地址:https://www.cnblogs.com/besti155214/p/7856952.html
Copyright © 2011-2022 走看看