• 2019-2020-1 20175325石淦铭《信息安全系统设计基础》实验三 《并发程序》


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

    任务一:

    • 学习使用Linux命令wc(1)
    • 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
    • 客户端传一个文本文件给服务器
    • 服务器返加文本文件中的单词数
    • 上方提交代码
    • 附件提交测试截图,至少要测试附件中的两个文件

    步骤:

    • wc指令功能:统计指定文件中的字节数、字数、行数,并将统计结果显示输出。
    • wc指令格式:wc [选项] 文件
    • wc命令参数:
      • c 统计字节数。
      • l 统计行数。
      • m 统计字符数,不能与 -c 标志一起使用。
      • w 统计字数。
      • L 打印最长行的长度。
      • -help:显示帮助信息
      • --version:显示版本信息
    • 实现伪代码:
      fd = fopen()//打开文件;
      fscanf()//对文件的内容以字符串的形式进行读取
      if..count++//设置条件,当满足字符串条件时计数;
    • 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 175325
    
    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 175325
    
    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);
    }
    
    • 实验截图:



    任务二:

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

    步骤:

    • 对比单线程版本的性能,分析原因如下:

    单线程比较稳定易于实现,运行稳定。而采用多线程可能不会提高程序的执行速度,反而会降低速度,同时,同步应用程序的开发比较容易,但由于需要在上一个任务完成后才能开始新的任务,其效率通常比多线程应用程序低

    • 重新编写支持多线程的服务器程序,然后编译,执行同上步
    • 实验截图:

    任务三:

    • 交叉编译多线程版本服务器并部署到实验箱中
    • PC机作客户端测试wc服务器
    • 提交测试截图
    • 关键代码:
    HANDLE CreateThread(  
    LPSECURITY_ATTRIBUTES lpThreadAttributes,
     //指向结构体SECURITY_ATTRIBUTES的指针,表示指定新建线程的安全属性
    DWORD dwStackSize,
     //指定线程初始化时地址空间的大小
    LPTHREAD_START_ROUTINE lpStartAddress,
    //指定该线程的线程函数的地址   
    LPVOID lpParameter,
    //将要传递给新建线程的命令行参数                
    DWORD dwCreationFlags, 
    //指定新建线程创建后是否立即执行                
    LPDWORD lpThreadId   ); 
    //表示新建线程的ID号
    
    • 执行:
      通过命令行即可实现交叉编译:
      • /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
  • 相关阅读:
    MetaWeblog API
    序列化Hashtable
    贴几个CodeDOM的链接
    Summing it all up: 35 blog entries in 2 days from the BCL Team [Kit George] --from BCLTeam's Weblog
    上海在下尘土
    PSP升级速度令然惊喜!(update:2007.10.13)
    Linkin Park林肯公园上海演唱会(2007年11月18日)
    STARCRAFT2 / 星际争霸2
    Enterprise Library 3.0 April 2007
    《The Devil Wears Prada / 穿布拉达的女王》很有意思.
  • 原文地址:https://www.cnblogs.com/sgm5/p/11887349.html
Copyright © 2020-2023  润新知