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\n",recv(connfd,rbuf,MAXLINE,0));   
        fputs(rbuf,fp);
     
        count += wc(rbuf);

        bzero(rbuf,sizeof(rbuf));
        }


        //printf("传输成功!,该文件单词数共%d\n!",count);

        fclose(fp);

        itoa(count,sbuf);

        //send(connfd,sbuf,MAXLINE,0);
       
        printf("该文件单词数为%s!\n",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即可实现交叉编译。
posted @ 2017-11-19 23:02  曾士轩  阅读(208)  评论(1编辑  收藏  举报