zoukankan      html  css  js  c++  java
  • 2017-2018-1 20155323 实验三 实时系统

    实验三 并发程序

    1.学习使用Linux命令wc(1)

    要求:

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

    实验过程

    • 首先是用man wc命令学习wc的用法

    wc命令参数:

    (1)-c:统计字节数。

    (2)-l:统计行数。

    (3)-m:统计字符数。这个标志不能与 -c 标志一起使用。

    (4)-w:统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。

    (5)-L:打印最长行的长度。

    (6)-help:显示帮助信息

    (7)--version:显示版本信息

    • 然后是编写客户端和服务器代码

    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 155323 
    #define LENGTH_OF_LISTEN_QUEUE 20  
    #define BUFFER_SIZE 1024
    #define FILE_NAME_MAX_SIZE 512  
    #define BEGIN 1; 
    
    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);
    
    char sendbuf[50];
    sprintf(sendbuf,"%d",words);
    
    send(new_server_socket_fd,sendbuf,50,0);
    
        close(new_server_socket_fd);  
    }  
    
    close(server_socket_fd);  
    return 0;  
    }
    

    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 155323  
    #define BUFFER_SIZE 1024  
    #define FILE_NAME_MAX_SIZE 512  
    #define BEGIN 1;
    
    int main()  
    {  
    
    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",50,0);
    
    char recvdata[sizeof(int)+1];
    recv(client_socket_fd,recvdata,sizeof(int),0);
    recvdata[sizeof(int)]='';
    int words=atoi(recvdata);
    close(client_socket_fd);  
    return 0;  
    }
    
    • 下一步编译客户端和服务器的代码生成可执行文件,先打开服务器,再打开客户端。然后用客户端向服务器传文件,最后再用wc -t命令检验统计字符数是否正确。

    2.使用多线程实现wc服务器并使用同步互斥机制保证计数正确

    要求:

    • 1.上方提交代码
    • 2.下方提交测试
    • 3.对比单线程版本的性能,并分析原因

    实验过程:

    • 首先是对pthread库的理解

    • 然后重新编写一个多线程服务器代码
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <sys/time.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <pthread.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <unistd.h>
    #define PORT  8888
    #define BACKLOG 10
    #define MAXCONN 100
    #define BUFFSIZE 1024
    typedef unsigned char BYTE;
    typedef struct ClientInfo
    {
    struct sockaddr_in addr;
    int clientfd;
    int isConn;
    int index;
    } ClientInfo;
    pthread_mutex_t activeConnMutex;
    pthread_mutex_t clientsMutex[MAXCONN];
    pthread_cond_t connDis;
    pthread_t threadID[MAXCONN];
    pthread_t serverManagerID;
    ClientInfo clients[MAXCONN];
    int serverExit = 0;
    
    void tolowerString(char *s)
    {
    int i=0;
    while(i < strlen(s))
    {
        s[i] = tolower(s[i]);
        ++i;
    } 
    }
    void listAll(char *all)
    {
    int i=0, len = 0;
    len += sprintf(all+len, "Index   		IP Address   		Port
    ");
    for(;i<MAXCONN;++i)
    {
        pthread_mutex_lock(&clientsMutex[i]);
        if(clients[i].isConn)
            len += sprintf(all+len, "%.8d		%s		%d
    ",clients[i].index, inet_ntoa(clients[i].addr.sin_addr), clients[i].addr.sin_port);
        pthread_mutex_unlock(&clientsMutex[i]);
    }
    }
    void clientManager(void* argv)
    {
    ClientInfo *client = (ClientInfo *)(argv);
    
    BYTE buff[BUFFSIZE];
    int recvbytes;
    
    int i=0;
    int clientfd = client->clientfd;
    struct sockaddr_in addr = client->addr;
    int isConn = client->isConn;
    int clientIndex = client->index;
    
    while((recvbytes = recv(clientfd, buff, BUFFSIZE, 0)) != -1)
    {
     
        tolowerString(buff);    
        
        char cmd[100];
        if((sscanf(buff, "%s", cmd)) == -1)    
        { 
           char err[100];         
           if(send(clientfd, err, strlen(err)+1, 0) == -1)
           {
               strcpy(err, "Error command and please enter again!
    ");
               fprintf(stdout, "%d sends an eroor command
    ", clientfd);
               break;
           }
        }
        else    
        {
            char msg[BUFFSIZE]; 
            int dest = clientIndex; 
            int isMsg = 0;             
            if(strcmp(cmd, "disconn") == 0)
            {   
                pthread_cond_signal(&connDis); 
                break;
            }
            else if(strcmp(cmd, "time") == 0)
            {
                time_t now;
                struct tm *timenow;
                time(&now);
                timenow = localtime(&now);
                strcpy(msg, asctime(timenow));
                isMsg = 1;
            }
            else if(strcmp(cmd, "name") == 0)
            {
                strcpy(msg, "MACHINE NAME");
                isMsg = 1;
            }
            else if(strcmp(cmd, "list") == 0)
            {                            
                listAll(msg);
                isMsg = 1;
            }
            else if(strcmp(cmd, "send") == 0)
            {   
                    
                if(sscanf(buff+strlen(cmd)+1, "%d%s", &dest, msg)==-1 || dest >= MAXCONN)
                {
                    char err[100];
                    strcpy(err, "Destination ID error and please use list to check and enter again!
    ");
                    fprintf(stderr, "Close %d client eroor: %s(errno: %d)
    ", clientfd, strerror(errno), errno);
                    break;
                }
                fprintf(stdout, "%d %s
    ", dest, msg);   
                isMsg = 1;
            }
            else
            {
                char err[100];
                strcpy(err, "Unknown command and please enter again!
    ");
                fprintf(stderr, "Send to %d message eroor: %s(errno: %d)
    ", clientfd, strerror(errno), errno);
                break;
            }
            
            
            if(isMsg)
            {
                pthread_mutex_lock(&clientsMutex[dest]);
                if(clients[dest].isConn == 0)
                {
                    sprintf(msg, "The destination is disconneted!");
                    dest = clientIndex; 
                } 
                            
                if(send(clients[dest].clientfd, msg, strlen(msg)+1, 0) == -1)
                {
                    fprintf(stderr, "Send to %d message eroor: %s(errno: %d)
    ", clientfd, strerror(errno), errno);
                    pthread_mutex_unlock(&clientsMutex[dest]); 
                    break;
                }
                printf("send successfully!
    ");
                pthread_mutex_unlock(&clientsMutex[dest]); 
            }
        }      
    }  
    
    pthread_mutex_lock(&clientsMutex[clientIndex]);
    client->isConn = 0;
    pthread_mutex_unlock(&clientsMutex[clientIndex]);
    
    if(close(clientfd) == -1)
        fprintf(stderr, "Close %d client eroor: %s(errno: %d)
    ", clientfd, strerror(errno), errno);
    fprintf(stderr, "Client %d connetion is closed
    ", clientfd);
    
    pthread_exit(NULL);
    }
    void serverManager(void* argv)
    {
    while(1)
    {
        char cmd[100];
        scanf("%s", cmd);
        tolowerString(cmd);
        if(strcmp(cmd, "exit") == 0)
            serverExit = 1;
        else if(strcmp(cmd, "list") == 0)
        {
            char buff[BUFFSIZE];
            listAll(buff);
            fprintf(stdout, "%s", buff);
        }
        else if(strcmp(cmd, "kill") == 0)
        {
            int clientIndex;
            scanf("%d", &clientIndex);
            if(clientIndex >= MAXCONN)
            {
                fprintf(stderr, "Unkown client!
    ");
                continue;
            }
            pthread_mutex_lock(&clientsMutex[clientIndex]);
            if(clients[clientIndex].isConn)
            {
                if(close(clients[clientIndex].clientfd) == -1)
                    fprintf(stderr, "Close %d client eroor: %s(errno: %d)
    ", clients[clientIndex].clientfd, strerror(errno), errno);
            }
            else
            {
                fprintf(stderr, "Unknown client!
    ");
            }
            pthread_mutex_unlock(&clientsMutex[clientIndex]);
            pthread_cancel(threadID[clientIndex]);
                
        }
        else
        {
            fprintf(stderr, "Unknown command!
    ");
        }
    }
    }
    int main()
    {
       		int activeConn = 0;
    
       	pthread_mutex_init(&activeConnMutex, NULL);   
       pthread_cond_init(&connDis, NULL);
       int i=0;
       	for(;i<MAXCONN;++i)
       pthread_mutex_init(&clientsMutex[i], NULL); 
    
       for(i=0;i<MAXCONN;++i)
       clients[i].isConn = 0; 
       
    
       pthread_create(&serverManagerID, NULL, (void *)(serverManager), NULL);
    
    
       int listenfd;
       struct sockaddr_in  servaddr;
    
    
       if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
       {
       fprintf(stderr, "Create socket error: %s(errno: %d)
    ", strerror(errno), errno);
       exit(0);
       }
       else
       fprintf(stdout, "Create a socket successfully
    ");
    
       fcntl(listenfd, F_SETFL, O_NONBLOCK);       
    
       memset(&servaddr, 0, sizeof(servaddr));  
       servaddr.sin_family = AF_INET;           
       servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    
       servaddr.sin_port = htons(PORT);           
    
    
       if(bind(listenfd, (struct sockaddr*)(&servaddr), sizeof(servaddr)) == -1)
       {
        fprintf(stderr, "Bind socket error: %s(errno: %d)
    ", strerror(errno), errno);
        exit(0);
       }
       else
       fprintf(stdout, "Bind socket successfully
    ");
    
      
       if(listen(listenfd, BACKLOG) == -1)
       {
       fprintf(stderr, "Listen socket error: %s(errno: %d)
    ", strerror(errno), errno);
       exit(0);
    }
       else
       fprintf(stdout, "Listen socket successfully
    ");
    
    
       while(1)
       {
       if(serverExit)
       {
           for(i=0;i<MAXCONN;++i)
           {
               if(clients[i].isConn)
               {
                   if(close(clients[i].clientfd) == -1)         
                       fprintf(stderr, "Close %d client eroor: %s(errno: %d)
    ", clients[i].clientfd, strerror(errno), errno);
                   if(pthread_cancel(threadID[i]) != 0)         
                        fprintf(stderr, "Cancel %d thread eroor: %s(errno: %d)
    ", (int)(threadID[i]), strerror(errno), errno);
               }
           }
           return 0;   
       }
       
       pthread_mutex_lock(&activeConnMutex);
       if(activeConn >= MAXCONN)
            pthread_cond_wait(&connDis, &activeConnMutex);
       pthread_mutex_unlock(&activeConnMutex);
           
       
       int i=0;
       while(i<MAXCONN)
       {
           pthread_mutex_lock(&clientsMutex[i]);
           if(!clients[i].isConn)
           {
               pthread_mutex_unlock(&clientsMutex[i]);
               break;
           }
           pthread_mutex_unlock(&clientsMutex[i]);
           ++i;           
       }   
       
    
       struct sockaddr_in addr;
       int clientfd;
       int sin_size = sizeof(struct sockaddr_in);
       if((clientfd = accept(listenfd, (struct sockaddr*)(&addr), &sin_size)) == -1)
       {   
           sleep(1);        
           
           continue;
           
       }
       else
           fprintf(stdout, "Accept socket successfully
    ");
       
       pthread_mutex_lock(&clientsMutex[i]);
       clients[i].clientfd = clientfd;
       clients[i].addr = addr;
       clients[i].isConn = 1;
       clients[i].index = i;
       pthread_mutex_unlock(&clientsMutex[i]);
       
       //create a thread for a client
       pthread_create(&threadID[i], NULL, (void *)clientManager, &clients[i]);     
       
       }    //end-while
    }
    
    • 编译后打开服务器,再照上一题的步骤分别打开两个客户端传文件

    • 多线程的优点:

    (1)多线程技术使程序的响应速度更快 ,因为用户界面可以在进行其它工作的同时一直处于活动状态;

    (2)当前没有进行处理的任务时可以将处理器时间让给其它任务;

    (3)占用大量处理时间的任务可以定期将处理器时间让给其它任务;

    (4)可以随时停止任务;

    (5)可以分别设置各个任务的优先级以优化性能。

    • 是否需要创建多个线程取决于各种因素。在以下情况下,最适合采用多线程处理:

    (1)耗时或大量占用处理器的任务阻塞用户界面操作;

    (2)各个任务必须等待外部资源 (如远程文件或 Internet连接)。

    多线程的优缺点

  • 相关阅读:
    Nginx出现10055错误问题
    MVC报错的坑
    用Docker运行一个简单RazorDemo(一)
    dotnet run
    用Docker 在Centos7上部署Core2.1网站
    VS2015 自己用的插件
    帐户当前被锁定,所以用户 sa 登录失败。系统管理员无法将该帐户解锁
    加密方法汇总
    【备用】网页抓取、
    【转】项目奖金分配
  • 原文地址:https://www.cnblogs.com/fixedl/p/7853641.html
Copyright © 2011-2022 走看看