zoukankan      html  css  js  c++  java
  • 2019-2020-1 20175230 实验三 并发程序

    实验三 并发程序

    任务一

    实验内容和要求

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

    实验步骤

    • 1.在命令行中使用命令man 1 wc查找wc(1)

    • 2.命令格式:
      wc [选项]文件...

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

    • 4.命令参数:
      -c 统计字节数。
      -l 统计行数。
      -m 统计字符数。这个标志不能与 -c 标志一起使用。
      -w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。
      -L 打印最长行的长度。
      -help 显示帮助信息
      -version 显示版本信息
      wc -w统计单词数:
      wc -w 与我们平时统计单词数的方法有点不同,wc -w命令实现时:由' ',' ',' ',' '作为分隔符,而实际上我们统计单词的分隔符还有'!'等等,因此针对两种不同的分隔符实现两种计算方法

    • 5.编写代码

    客户端

    /*client*/
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    #define MYPORT 175230
    
    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);
    }
    

    服务器端

    /*server*/
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    
    #define MYPORT 175230
    
    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);
    }
    
    • 6.实验结果

    任务二

    实验内容与要求

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

    实验步骤

    • 1.编写代码
      客户端
    #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 175230
    #define BUFFER_SIZE 1024
    #define FILE_NAME_MAX_SIZE 512
    
    int mywc(char file_name[], int choose);
    
    int main(int argc, char **argv) {
        char *ipaddr = "127.0.0.1";
        FILE *fp;
        if (argc != 1) {
            printf("Usage: ./%s ServerIPAddress
    ", ipaddr);
            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(ipaddr, &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!
    ", ipaddr);
            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, 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);
        }
        
        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;
    }
    

    服务器

    #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 175230
    #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;
        FILE *fp;
        printf("实现“wc -w”:
    ");
        if ((fp = fopen(file_name, "r")) == NULL) {
            printf("Failure to open %s
    ", file_name);
            exit(0);
        }
    
        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);
    } 
    

    实验结果

    任务三

    实验内容与要求

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

    实验步骤

    -1.实验箱与电脑互相ping通

    实验结果

    未能得出实验结果

    实验中遇到的问题

    • 1.问题一
      在统计完单词数之后服务器端没有停止进程,继续监听,等待从客户端发来的信号,无法停止
      解决方法:强行使用Ctrl+C强制结束进程

    • 2.问题1:Fatal error: stdafx.h : No such file or directory
      问题1解决方案:建工程自带,将其删除即可;或者是手动添加头文件

  • 相关阅读:
    第一次实习项目总结
    javascript整理笔记(一)-----写项目的小技巧
    Vue(项目踩坑)_These dependencies were not found: * !!vue-style-loader!css-loader?{"sourceMap":true}!../../../node_modules/vue-loader/lib/style-compiler/index?{"vue"
    JS(递归-记一次面试题)-写一个get函数,get({a:1}, 'a')输出1,get({a : {b:2}},‘a.b’)输出2,按照此规律写一个函数
    html5_音视频的兼容性写法
    canvas_画出图片的马赛克
    项目(踩坑)_移动端在使用touch滑动事件的时候会出现抖动现象
    vue+mongoose+node.js项目总结第七篇_express框架中使用socket.io插件实现在线聊天功能(前端消息发送-后端接收逻辑)
    网址
    RAII Theory && auto_ptr
  • 原文地址:https://www.cnblogs.com/tengxing/p/11923877.html
Copyright © 2011-2022 走看看