• 2018-2019-1 20165232 实验三


    2018-2019-1 20165232 实验三 并发程序

    并发程序-1

    实验要求

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

    实验步骤

    • man wc命令学习wc命令的使用
    1. wc指令功能:统计指定文件中的字节数、字数、行数,并将统计结果显示输出。
    2. wc指令格式:wc [选项] 文件...
      wc指令描述:其中word字长是由空格分隔的非零长度序列。
    3. wc命令参数:
    • c 统计字节数。
    • l 统计行数。
    • m 统计字符数。这个标志不能与 -c 标志一起使用。
    • w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。
    • L 打印最长行的长度。

    本题代码

    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 165232  
    #define LENGTH_OF_LISTEN_QUEUE 20  
    #define BUFFER_SIZE 1024
    #define FILE_NAME_MAX_SIZE 512  
    
    int main(void)  
    {  
        
        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);  
    
          
        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));  
    
        
        if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))  
        {  
            perror("Server Bind Failed:");  
            exit(1);  
        }  
    
       
        if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))  
        {  
            perror("Server Listen Failed:");  
            exit(1);  
        }  
    
        while(1)  
        {  
           
            struct sockaddr_in client_addr;  
            socklen_t client_addr_length = sizeof(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;  
            }  
    
            
            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;  
            }  
    
            
            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);  
            }  
    
        
            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);  
            }  
    
    
       
            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);  
    
    
    
    
        }  
        
        close(server_socket_fd);  
        return 0;  
    }
    

    client.c:

    #include<netinet/in.h>     
    #include<sys/types.h>     
    #include<sys/socket.h>   
    #include<stdio.h>        
    #include<stdlib.h>        
    #include<string.h>        
    
    #define SERVER_PORT 165232  
    #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);  
    
          
        int client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);  
        if(client_socket_fd < 0)  
        {  
            perror("Create Socket Failed:");  
            exit(1);  
        }  
    
        
        if(-1 == (bind(client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr))))  
        {  
            perror("Client Bind Failed:");  
            exit(1);  
        }  
    
        
        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);  
    
       
        if(connect(client_socket_fd, (struct sockaddr*)&server_addr, server_addr_length) < 0)  
        {  
            perror("Can Not Connect To Server IP:");  
            exit(0);  
        }  
    
        
        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));  
    
        
        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;  
    }
    

    运行结果
    image

    并发程序-2

    实验要求

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

    实验步骤

    • man pthread命令学习pthread相关调用

    代码
    thread_server.c

    #include<stdlib.h>
    #include<pthread.h>
    #include<sys/socket.h>
    #include<sys/types.h>       //pthread_t , pthread_attr_t and so on.
    #include<stdio.h>
    #include<netinet/in.h>      //structure sockaddr_in
    #include<arpa/inet.h>       //Func : htonl; htons; ntohl; ntohs
    #include<assert.h>          //Func :assert
    #include<string.h>          //Func :memset bzero
    #include<unistd.h>          //Func :close,write,read
    #define SOCK_PORT 9988
    #define BUFFER_LENGTH 1024
    #define MAX_CONN_LIMIT 512     //MAX connection limit
    static void Data_handle(void * sock_fd);   //Only can be seen in the file
    int CountWordsOfEuropeanTxtFile(char *szFileName);
    int CountWordsInOneLine(const char *szLine);
    int main()
    {
        int sockfd_server;
        int sockfd;
        int fd_temp;
        struct sockaddr_in s_addr_in;
        struct sockaddr_in s_addr_client;
        int client_length;
        sockfd_server = socket(AF_INET,SOCK_STREAM,0);  //ipv4,TCP
        assert(sockfd_server != -1);
        //before bind(), set the attr of structure sockaddr.
        memset(&s_addr_in,0,sizeof(s_addr_in));
        s_addr_in.sin_family = AF_INET;
        s_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);  //trans addr from uint32_t host byte order to network byte order.
        s_addr_in.sin_port = htons(SOCK_PORT);          //trans port from uint16_t host byte order to network byte order.
        fd_temp = bind(sockfd_server,(const struct sockaddr *)(&s_addr_in),sizeof(s_addr_in));
        if(fd_temp == -1)
        {
            fprintf(stderr,"bind error!
    ");
            exit(1);
        }
        fd_temp = listen(sockfd_server,MAX_CONN_LIMIT);
        if(fd_temp == -1)
        {
            fprintf(stderr,"listen error!
    ");
            exit(1);
        }
        while(1)
        {
            printf("waiting for new connection...
    ");
            pthread_t thread_id;
            client_length = sizeof(s_addr_client);
            //Block here. Until server accpets a new connection.
            sockfd = accept(sockfd_server,(struct sockaddr * restrict)(&s_addr_client),(socklen_t *)(&client_length));
            if(sockfd == -1)
            {
                fprintf(stderr,"Accept error!
    ");
                continue;                               //ignore current socket ,continue while loop.
            }
            printf("A new connection occurs!
    ");
            if(pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd)) == -1)
            {
                fprintf(stderr,"pthread_create error!
    ");
                break;                                  //break while loop
            }
        }
        //Clear
        int ret = shutdown(sockfd_server,SHUT_WR); //shut down the all or part of a full-duplex connection.
        assert(ret != -1);
        printf("Server shuts down
    ");
        return 0;
    }
    static void Data_handle(void * sock_fd)
    {
        int fd = *((int *)sock_fd);
        int i_recvBytes;
        char data_recv[BUFFER_LENGTH];
        const char * data_send = "Server has received your request!
    ";
        while(1)
        {
            printf("waiting for file_name...
    ");
            //Reset data.
            memset(data_recv,0,BUFFER_LENGTH);
            i_recvBytes = read(fd,data_recv,BUFFER_LENGTH);
            if(i_recvBytes == 0)
            {
                printf("Maybe the client has closed
    ");
                break;
            }
            if(i_recvBytes == -1)
            {
                fprintf(stderr,"read error!
    ");
                break;
            }
            if(strcmp(data_recv,"quit")==0)
            {
                printf("Quit command!
    ");
                break;                           //Break the while loop.
            }
            printf("read from client : %s
    ",data_recv);
            
        char buffer[BUFFER_LENGTH];
        int count=0;
        bzero(buffer, BUFFER_LENGTH);
        count = CountWordsOfEuropeanTxtFile(data_recv);
        sprintf(buffer,"%d", count);
            send(fd, buffer, sizeof(buffer), 0);
            if(write(fd,data_send,strlen(data_send)) == -1)
            {
                break;
            }
        }
        //Clear
        printf("terminating current client_connection...
    ");
        close(fd);            //close a file descriptor.
        pthread_exit(NULL);   //terminate calling thread!
    }
    int CountWordsOfEuropeanTxtFile(char *szFileName)
    {
        int nWords = 0;//词计数变量,初始值为0
        FILE *fp; //文件指针
        char carrBuffer[1024];//每行字符缓冲,每行最多1024个字符
        //打开文件
        if ((fp = fopen(szFileName,  "r")) == NULL)
        {
            return -1;  //文件打开不成功是返回-1
        }
        while (!feof(fp))//如果没有读到文件末尾 
        {
            //从文件中读一行
            if (fgets(carrBuffer, sizeof(carrBuffer),fp) != NULL)
                //统计每行词数
                nWords += CountWordsInOneLine(carrBuffer);
        }
    
        //关闭文件
        fclose(fp);
        return nWords;
    }
    int CountWordsInOneLine(const char *szLine)
    {
        int nWords = 0;
        int i=0;
        for (;i<strlen(szLine);i++)
        {
            if (*(szLine+i)!=' ')
            {
                nWords++;
                while ((*(szLine+i)!=' ')&&(*(szLine+i)!=''))
                {
                    i++;
                }
            }
    
        }
                //printf("%d	",nWords);
        
        return nWords;
    }
    

    thread_client.c

    #include<stdlib.h>
    #include<sys/socket.h>
    #include<sys/types.h>       //pthread_t , pthread_attr_t and so on.
    #include<stdio.h>
    #include<netinet/in.h>      //structure sockaddr_in
    #include<arpa/inet.h>       //Func : htonl; htons; ntohl; ntohs
    #include<assert.h>          //Func :assert
    #include<string.h>          //Func :memset bzero
    #include<unistd.h>          //Func :close,write,read
    #define SOCK_PORT 9988
    #define BUFFER_LENGTH 1024
    int main()
    {
        int sockfd;
        int tempfd;
        struct sockaddr_in s_addr_in;
        char data_send[BUFFER_LENGTH];
        char data_recv[BUFFER_LENGTH];
        memset(data_send,0,BUFFER_LENGTH);
        memset(data_recv,0,BUFFER_LENGTH);
        sockfd = socket(AF_INET,SOCK_STREAM,0);       //ipv4,TCP
        if(sockfd == -1)
        {
            fprintf(stderr,"socket error!
    ");
            exit(1);
        }
        //before func connect, set the attr of structure sockaddr.
        memset(&s_addr_in,0,sizeof(s_addr_in));
        s_addr_in.sin_addr.s_addr = inet_addr("127.0.0.1");      //trans char * to in_addr_t
        s_addr_in.sin_family = AF_INET;
        s_addr_in.sin_port = htons(SOCK_PORT);
        tempfd = connect(sockfd,(struct sockaddr *)(&s_addr_in),sizeof(s_addr_in));
        if(tempfd == -1)
        {
            fprintf(stderr,"Connect error! 
    ");
            exit(1);
        }
        while(1)
        {
            printf("Please Input File Name On Server(input "quit" to quit):	");
        scanf("%s", data_send);        
        //gets(data_send);
            //scanf("%[^
    ]",data_send);         //or you can also use this
            tempfd = write(sockfd,data_send,BUFFER_LENGTH);
            if(tempfd == -1)
            {
                fprintf(stderr,"write error
    ");
                exit(0);
            }
    
            if(strcmp(data_send,"quit") == 0)  //quit,write the quit request and shutdown client
            {
                break;
            }
            else
            {
                tempfd = read(sockfd,data_recv,BUFFER_LENGTH);
                assert(tempfd != -1);
                printf("%s
    ",data_recv);
                memset(data_send,0,BUFFER_LENGTH);
                memset(data_recv,0,BUFFER_LENGTH);
            }
        char buffer[BUFFER_LENGTH];
        int length=0;
        bzero(buffer, BUFFER_LENGTH);
            length = recv(sockfd, buffer, BUFFER_LENGTH, 0);
            buffer[length] = '';
            printf("count=%s
    ", buffer);
            bzero(buffer, BUFFER_LENGTH);
        }
        int ret = shutdown(sockfd,SHUT_WR);       //or you can use func close()--<unistd.h> to close the fd
        assert(ret != -1);
        return 0;
    }
    

    运行结果
    image

    实验遇到的问题

    实验二中编译server文件时提示“对‘pthread_create'未定义的引用”

    解决:编译时输入 gcc thread_server.c -o thread_server -lpthread即可。

  • 相关阅读:
    CentOS虚拟机和物理机共享文件夹实现
    集训第六周 数学概念与方法 概率 数论 最大公约数 G题
    集训第六周 数学概念与方法 概率 F题
    集训第六周 E题
    集训第六周 古典概型 期望 D题 Discovering Gold 期望
    集训第六周 古典概型 期望 C题
    集训第六周 数学概念与方法 UVA 11181 条件概率
    集训第六周 数学概念与方法 UVA 11722 几何概型
    DAG模型(矩形嵌套)
    集训第五周 动态规划 K题 背包
  • 原文地址:https://www.cnblogs.com/heyanda/p/9959047.html
Copyright © 2020-2023  润新知