zoukankan      html  css  js  c++  java
  • 2019-2020-1 20175310 20175317 20175320 实验三 实时系统

    2019-2020-1 20175310 20175317 20175320 实验三 实时系统

    小组成员

    20175310 奚晨妍

    20175317 钟睿文

    20175320 龚仕杰

    实验步骤

    一、并发程序-1

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

    #include<netinet/in.h>   // sockaddr_in  
    #include<sys/types.h>    // socket  
    #include<sys/socket.h>   // socket  
    #include<stdio.h>        // printf  
    #include<stdlib.h>       // exit  
    #include<string.h>       // bzero  
    
    #define SERVER_PORT 175317  
    #define BUFFER_SIZE 1024  
    #define FILE_NAME_MAX_SIZE 512  
    
    int main()  
    {  
        // 声明并初始化一个客户端的socket地址结构  
        struct sockaddr_in client_addr;  
        bzero(&client_addr, sizeof(client_addr));  
        client_addr.sin_family = AF_INET;  
        client_addr.sin_addr.s_addr = htons(INADDR_ANY);  
        client_addr.sin_port = htons(0);  
    
        // 创建socket,若成功,返回socket描述符  
        int client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);  
        if(client_socket_fd < 0)  
        {  
            perror("Create Socket Failed:");  
            exit(1);  
        }  
    
        // 绑定客户端的socket和客户端的socket地址结构 非必需  
        if(-1 == (bind(client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr))))  
        {  
            perror("Client Bind Failed:");  
            exit(1);  
        }  
    
        // 声明一个服务器端的socket地址结构,并用服务器那边的IP地址及端口对其进行初始化,用于后面的连接  
        struct sockaddr_in server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
        if(inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) == 0)  
        {  
            perror("Server IP Address Error:");  
            exit(1);  
        }  
        server_addr.sin_port = htons(SERVER_PORT);  
        socklen_t server_addr_length = sizeof(server_addr);  
    
        // 向服务器发起连接,连接成功后client_socket_fd代表了客户端和服务器的一个socket连接  
        if(connect(client_socket_fd, (struct sockaddr*)&server_addr, server_addr_length) < 0)  
        {  
            perror("Can Not Connect To Server IP:");  
            exit(0);  
        }  
    
        // 输入文件名,并放到缓冲区buffer中等待发送  
        char file_name[FILE_NAME_MAX_SIZE+1];  
        bzero(file_name, FILE_NAME_MAX_SIZE+1);  
    
        printf("Please Input File Name On Client:
    ");
        scanf("%s", file_name);  
    
        char buffer[BUFFER_SIZE];  
        bzero(buffer, BUFFER_SIZE);  
        strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name));  
    
        // 向服务器发送buffer中的数据  
        if(send(client_socket_fd, buffer, BUFFER_SIZE, 0) < 0)  
        {  
            perror("Send File Name Failed:");  
            exit(1);  
        }  
    
    
        // 打开文件并读取文件数据  
            FILE *fp = fopen(file_name, "r");  
            if(NULL == fp)  
            {  
                printf("File:%s Not Found
    ", file_name);  
            }  
            else  
            {  
                bzero(buffer, BUFFER_SIZE);  
                int length = 0;  
                // 每读取一段数据,便将其发送给服务器,循环直到文件读完为止  
                while((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)  
                {  
                    if(send(client_socket_fd, buffer, length, 0) < 0)  
                    {  
                        printf("Send File:%s Failed./n", file_name);  
                        break;  
                    }  
                    bzero(buffer, BUFFER_SIZE);  
                }  
    
                // 关闭文件  
    
                fclose(fp);  
                printf("File:%s Transfer Successful!
    ", file_name);  
            char s[50]; 
            scanf("%s",s);
            send(client_socket_fd,"OK",BUFFER_SIZE,0);
            recv(client_socket_fd,buffer,BUFFER_SIZE,0);    
            printf("%d words.
    ",atoi(buffer));
        }  
    
        close(client_socket_fd);  
        return 0;  
    } 
    

    server.c

    #include<netinet/in.h>  // sockaddr_in  
    #include<sys/types.h>   // socket  
    #include<sys/socket.h>  // socket  
    #include<stdio.h>       // printf  
    #include<stdlib.h>      // exit  
    #include<string.h>      // bzero  
    
    #define SERVER_PORT 175317  
    #define LENGTH_OF_LISTEN_QUEUE 20  
    #define BUFFER_SIZE 1024
    #define FILE_NAME_MAX_SIZE 512  
    
    int main(void)  
    {  
        // 声明并初始化一个服务器端的socket地址结构  
        struct sockaddr_in server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
        server_addr.sin_addr.s_addr = htons(INADDR_ANY);  
        server_addr.sin_port = htons(SERVER_PORT);  
    
        // 创建socket,若成功,返回socket描述符  
        int server_socket_fd = socket(PF_INET, SOCK_STREAM, 0);  
        if(server_socket_fd < 0)  
        {  
            perror("Create Socket Failed:");  
            exit(1);  
        }  
        int opt = 1;  
        setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));  
    
        // 绑定socket和socket地址结构  
        if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))  
        {  
            perror("Server Bind Failed:");  
            exit(1);  
        }  
    
        // socket监听  
        if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))  
        {  
            perror("Server Listen Failed:");  
            exit(1);  
        }  
    
        while(1)  
        {  
            // 定义客户端的socket地址结构  
            struct sockaddr_in client_addr;  
            socklen_t client_addr_length = sizeof(client_addr);  
    
            // 接受连接请求,返回一个新的socket(描述符),这个新socket用于同连接的客户端通信  
            // accept函数会把连接到的客户端信息写到client_addr中  
            int new_server_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &client_addr_length);  
            if(new_server_socket_fd < 0)  
            {  
                perror("Server Accept Failed:");  
                break;  
            }  
    
           // recv函数接收数据到缓冲区buffer中  
            char buffer[BUFFER_SIZE];  
            bzero(buffer, BUFFER_SIZE);  
            if(recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0) < 0)  
            {  
                perror("Server Recieve Data Failed:");  
                break;  
            }  
    
            // 然后从buffer(缓冲区)拷贝到file_name中  
            char file_name[FILE_NAME_MAX_SIZE+1];  
            bzero(file_name, FILE_NAME_MAX_SIZE+1);  
            strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));  
            printf("%s
    ", file_name);  
    
        // 打开文件,准备写入  
            FILE *fp = fopen(file_name, "w");  
            if(NULL == fp)  
            {  
                printf("File:	%s Can Not Open To Write
    ", file_name);  
                exit(1);  
            }  
    
        // 从客户端接收数据到buffer中  
            // 每接收一段数据,便将其写入文件中,循环直到文件接收完并写完为止  
            bzero(buffer, BUFFER_SIZE);  
            int length = 0;  
            while((length = recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0)) > 0)  
            {  
            if(strcmp(buffer,"OK")==0) break;
                if(fwrite(buffer, sizeof(char), length, fp) < length)  
                {  
                    printf("File:	%s Write Failed
    ", file_name);  
                    break;  
                }  
                bzero(buffer, BUFFER_SIZE);  
            }  
    
    
        // 接收成功后,关闭文件,关闭socket  
            printf("Receive File:	%s From Client IP Successful!
    ", file_name);  
            fclose(fp);
    
    
        // 统计文件单词个数,并发送给客户端
        int words=0;
        char s[100];
        FILE *fp2;
        if((fp2=fopen(file_name,"r"))==NULL){
            printf("ERROR!
    ");
            exit(0);
        }
        while(fscanf(fp2,"%s",s)!=EOF)
            words++;
        fclose(fp2);
        //printf("%d words.
    ",words);
    
    
        sprintf(buffer,"%d",words);
    
        send(new_server_socket_fd,buffer,BUFFER_SIZE,0);
    
        //send(new_server_socket_fd,&words,sizeof(words),0);
        close(new_server_socket_fd);  
    
    
    
            // 关闭与客户端的连接  
    
        }  
        // 关闭监听用的socket  
        close(server_socket_fd);  
        return 0;  
    } 
    
    

    学习wc:

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数、字数、行数,并将统计结果显示输出。

    命令参数:
    -c 统计字节数。
    -l 统计行数。
    -m 统计字符数。这个标志不能与 -c 标志一起使用。
    -w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。
    -L 打印最长行的长度。
    

    实验截图:


    二、并发程序-2

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

    #include<netinet/in.h>                         // for sockaddr_in  
    #include<sys/types.h>                          // for socket  
    #include<sys/socket.h>                         // for socket  
    #include<stdio.h>                              // for printf  
    #include<stdlib.h>                             // for exit  
    #include<string.h>                             // for bzero  
      
    #define HELLO_WORLD_SERVER_PORT       175317  
    #define BUFFER_SIZE                   1024  
    #define FILE_NAME_MAX_SIZE            512  
    int mywc(char file_name[],int choose);
    int main(int argc, char **argv)  
    {  
        FILE *fp;
        if (argc != 2)  
        {  
            printf("Usage: ./%s ServerIPAddress
    ", argv[0]);  
            exit(1);  
        }  
    
    // 设置一个socket地址结构client_addr, 代表客户机的internet地址和端口  
        struct sockaddr_in client_addr;  
        bzero(&client_addr, sizeof(client_addr));  
        client_addr.sin_family = AF_INET; // internet协议族  
        client_addr.sin_addr.s_addr = htons(INADDR_ANY); // INADDR_ANY表示自动获取本机地址  
        client_addr.sin_port = htons(0); // auto allocated, 让系统自动分配一个空闲端口  
    
    // 创建用于internet的流协议(TCP)类型socket,用client_socket代表客户端socket  
        int client_socket = socket(AF_INET, SOCK_STREAM, 0);  
        if (client_socket < 0)  
        {  
            printf("Create Socket Failed!
    ");  
            exit(1);  
        }  
    
    // 把客户端的socket和客户端的socket地址结构绑定   
        if (bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)))  
        {  
            printf("Client Bind Port Failed!
    ");  
            exit(1);  
        }  
    
    // 设置一个socket地址结构server_addr,代表服务器的internet地址和端口  
        struct sockaddr_in  server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
    
    // 服务器的IP地址来自程序的参数   
        if (inet_aton(argv[1], &server_addr.sin_addr) == 0)  
        {  
            printf("Server IP Address Error!
    ");  
            exit(1);  
        }                                                                                                               
        server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
        socklen_t server_addr_length = sizeof(server_addr);  
        // 向服务器发起连接请求,连接成功后client_socket代表客户端和服务器端的一个socket连接  
        if (connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length) < 0)  
        {  
            printf("Can Not Connect To %s!
    ", argv[1]);  
            exit(1);  
        }  
    
        char file_name[FILE_NAME_MAX_SIZE + 1];  
        bzero(file_name, sizeof(file_name));  
        printf("Please Input File Name.	");  
        scanf("%s", file_name);  
        if((fp = fopen(file_name,"r"))==NULL)
        {
             printf("Failure to open %s
    ",file_name);
             exit(0);
        }
        
        char buffer[BUFFER_SIZE];  
        bzero(buffer, sizeof(buffer));  
        strcpy(buffer,file_name);
        if(send(client_socket,buffer,BUFFER_SIZE,0)==-1)
        {
            printf("发送文件名失败
    ");
        }
        char ch;
        int i=0;
        while((ch=fgetc(fp))!=EOF)
        {
            buffer[i++]=ch;
            if(i>=BUFFER_SIZE)
            {
                if((send(client_socket, buffer, BUFFER_SIZE, 0))==-1)
                {
                    printf("发送文件失败
    ");
                }
                bzero(buffer, sizeof(buffer));
                i=0;
            }
        }
        if(i<BUFFER_SIZE)
        {
            if((send(client_socket, buffer, i, 0))==-1)
            {
                printf("发送文件失败
    ");
            }
        }
        printf("发送%s完毕
    ",file_name);
        mywc(file_name,1);
         mywc(file_name,2);
        // 向服务器发送buffer中的数据,此时buffer中存放的是客户端需要接收的文件 
        //以下接收服务器发来的单词个数
        bzero(buffer, sizeof(buffer));
    
        fclose(fp);  
        close(client_socket);  
        return 0;  
    
    }  
     int mywc(char file_name[],int choose)
      {
           FILE *fp;
           char ch;
            int flag=0,num=0;
           
                if((fp = fopen(file_name,"r"))==NULL)
                 {
                      printf("Failure to open %s
    ",file_name);
                       exit(0);
                    }
                 
                      if(choose==1)
                       {
                        while((ch=fgetc(fp))!=EOF)
                         {
                              if(ch==' ' || ch=='
    ' || ch=='	' ||  ch=='!' || ch=='?' || ch=='"' || ch=='.' || ch== '\,' || ch==':' || ch=='(' || ch==')' || ch==';'     || ch=='-')
                              {
                              flag=0;
                              }
                              else
                              {
                              if(flag==0)
                              {
                              flag=1;
                              num++;
                              }
                              
                              }
    
                        }
    
                    }
                    else if(choose==2)
                    {
                        while((ch=fgetc(fp))!=EOF)
                        {
                            if(ch==' ' || ch=='
    ' || ch=='	' || ch=='
    ')
                            flag=0;
                            else
                            {
                                if(flag==0)
                                {
                                    flag=1;
                                    num++;
                                }
                            }
                        }
                    }
                    printf("单词个数为:%d_用方式%d计算
    ",num,choose);
                    fclose(fp);
                    return num;
    }
    
    

    server.c

    #include<netinet/in.h>   
    #include<sys/types.h>   
    #include<sys/socket.h>   
    #include<stdio.h>   
    #include<stdlib.h>   
    #include<string.h>   
    #include<pthread.h>  
    #define HELLO_WORLD_SERVER_PORT    175317  
    #define LENGTH_OF_LISTEN_QUEUE     20  
    #define BUFFER_SIZE                1024  
    #define FILE_NAME_MAX_SIZE         512  
    void *process_client(void *new_server_socket);
    int mywc(char file_name[])
    {
        char ch;
        int flag=0,num=0;
        int choose;
        FILE *fp;
        printf("统计单词个数还是实现“wc -w”?(1or2)
    ");
        scanf("%d",&choose);
        if((fp = fopen(file_name,"r"))==NULL)
        {
            printf("Failure to open %s
    ",file_name);
            exit(0);
        }
    
        if(choose==1)
        {
        while((ch=fgetc(fp))!=EOF)
        {
            if(ch==' ' || ch=='
    ' || ch=='	' ||  ch=='!' || ch=='?' || ch=='"' || ch=='.' || ch== '\,' || ch==':' || ch=='(' || ch==')' || ch==';' || ch=='-')
            {
                flag=0;
            }
            else
            {
                if(flag==0)
                {
                    flag=1;
                    num++;
                }
    
            }
                       
        }
    
        }
        else if(choose==2)
        {
            while((ch=fgetc(fp))!=EOF)
            {
                if(ch==' ' || ch=='
    ' || ch=='	' || ch=='
    ')
                    flag=0;
                else
                {
                    if(flag==0)
                    {
                        flag=1;
                        num++;
                    }
                }
            }
        }
        printf("单词个数为:%d
    ",num);
        fclose(fp);
        return num;
    }
    int main(int argc, char **argv)  
    {  
    // set socket's address information   
    // 设置一个socket地址结构server_addr,代表服务器internet的地址和端口  
        struct sockaddr_in   server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
        server_addr.sin_addr.s_addr = htons(INADDR_ANY);  
        server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
    // create a stream socket   
    // 创建用于internet的流协议(TCP)socket,用server_socket代表服务器向客户端提供服务的接口  
        int server_socket = socket(PF_INET, SOCK_STREAM, 0);  
        if (server_socket < 0)  
        {  
            printf("Create Socket Failed!
    ");  
            exit(1);  
        }  
    
    // 把socket和socket地址结构绑定   
        if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))  
        {  
            printf("Server Bind Port: %d Failed!
    ", HELLO_WORLD_SERVER_PORT);  
            exit(1);  
        }  
    
    // server_socket用于监听   
        if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))  
        {  
            printf("Server Listen Failed!
    ");  
            exit(1);  
        }  
    // 服务器端一直运行用以持续为客户端提供服务   
          
        while(1)
        {
    // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept  
    // 接受此请求,同时将client端的地址和端口等信息写入client_addr中  
            struct sockaddr_in client_addr;  
            socklen_t length = sizeof(client_addr);  
    
    
            int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);  
            printf("连接到客户端
    ");
            if (new_server_socket < 0)  
            {  
                printf("Server Accept Failed!
    ");  
                  
            }
            //添加进程相关代码
            pthread_t pid;
            if(pthread_create(&pid, NULL, process_client,(void *) &new_server_socket) < 0){
                  printf("pthread_create error
    ");
            }
            
        }
    //  close(server_socket);
    }
    void *process_client(void *new_server_socket)
    {
            int sockid=*(int *)new_server_socket;
            FILE *fp;
            //接受来自客户端的文件
            char buffer[BUFFER_SIZE]; 
            char file_name[FILE_NAME_MAX_SIZE];
            bzero(buffer, sizeof(buffer));  
            int length=0;
            if(recv(sockid,buffer,BUFFER_SIZE, 0)==-1)
            {
                printf("接受文件名%s失败
    ",buffer);
            }
            strcpy(file_name,buffer);
            strcat(file_name,"-server");
            if((fp = fopen(file_name,"w"))==NULL)
            {
                printf("Failure to open %s
    ",file_name);
                exit(0);
            }
            while( length = recv(sockid, buffer, BUFFER_SIZE, 0))
            {
                if(length<0)
                {
                    printf("接受文件出错
    ");
                    exit(0);
                }
                
                if(fwrite(buffer,sizeof(char),length,fp)<length)
                {
                    printf("写文件失败
    ");
                }
                bzero(buffer, BUFFER_SIZE);
            }
            fclose(fp);
            printf("接受文件完毕
    ");
            int number=0;
            number=mywc(file_name);
            bzero(buffer, BUFFER_SIZE);  
            buffer[0]=number+48;
     
         
            bzero(buffer, sizeof(buffer));  
            
    
            printf("File Transfer Finished!
    ");    
            close(new_server_socket);  
    } 
    
    

    实验截图:
    test3.txt


    分析原因:
    单线程比较稳定易于实现,运行稳定。而多线程由于创建和切换的开销,采用多线程可能不会提高程序的执行速度,反而会降低速度,但是对于频繁IO操作的程序,多线程可以有效的并发。

    三、并发程序-3

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

  • 相关阅读:
    257. Binary Tree Paths
    324. Wiggle Sort II
    315. Count of Smaller Numbers After Self
    350. Intersection of Two Arrays II
    295. Find Median from Data Stream
    289. Game of Life
    287. Find the Duplicate Number
    279. Perfect Squares
    384. Shuffle an Array
    E
  • 原文地址:https://www.cnblogs.com/20175317zrw/p/11918108.html
Copyright © 2011-2022 走看看