• 2018-2019-1 20165219 实验三 实时系统


    2018-2019-1 20165219 实验三 实时系统

    任务一

    实验要求

    学习使用Linux命令wc(1)

    基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端

    客户端传一个文本文件给服务器

    服务器返加文本文件中的单词数

    客户端

    #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 165219 
    #define BUFFER_SIZE 1024 
    #define FILE_NAME_MAX_SIZE 512 
      
    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 Server:	"); 
      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, "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(client_socket_fd, buffer, BUFFER_SIZE, 0)) > 0) 
      { 
        if(fwrite(buffer, sizeof(char), length, fp) < length) 
        { 
          printf("File:	%s Write Failed
    ", file_name); 
          break; 
        } 
        bzero(buffer, BUFFER_SIZE); 
      } 
    
      printf("Send File:	%s  Successful!
    ", file_name); 
      close(fp); 
      close(client_socket_fd);
      char *argv[]={"wc","-w",file_name,0};
      execvp("wc",argv);
      return 0; 
    } 
    

    服务器

    #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 8000
    #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, "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(new_server_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);
        }
        close(new_server_socket_fd);
      }
      close(server_socket_fd);
      return 0;
    }
    

    任务二

    实验要求

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

    上方提交代码

    下方提交测试

    对比单线程版本的性能,并分析原因

    服务器

    #include "csapp.h"
    #include<stdio.h>
    #include<stdlib.h>
    static int byte_cnt;  /* byte counter */
    static sem_t mutex;
    #define NTHREADS  4
    #define SBUFSIZE  16
    typedef struct {
        int *buf;          /* Buffer array */        
        int n;             /* Maximum number of slots */
        int front;         /* buf[(front+1)%n] is first item */
        int rear;          /* buf[rear%n] is last item */
        sem_t mutex;       /* Protects accesses to buf */
        sem_t slots;       /* Counts available slots */
        sem_t items;       /* Counts available items */
    } sbuf_t;
    void echo_cnt(int connfd);
    void *thread(void *vargp);
    int wc(char *name)
    {
     char ch;
     FILE *fp;
     long count=0;
     char s[21];
      
      
     if ((fp=fopen(name,"r+"))==NULL)
     {
      fprintf(stderr,"不能打开文件
    ");
      exit(EXIT_FAILURE);
     }
    while(fscanf(fp,"%s",s)!=EOF)
            count++;
      
     fclose(fp);
     printf("File %s has %ld characters
    ",name,count);
     return 0;
    }
     
    sbuf_t sbuf; /* shared buffer of connected descriptors */
     
    int main(int argc, char **argv)
    {
        int i, listenfd, connfd, port, clientlen=sizeof(struct sockaddr_in);
        struct sockaddr_in clientaddr;
        pthread_t tid;
     
        if (argc != 2) {
        fprintf(stderr, "usage: %s <port>
    ", argv[0]);
        exit(0);
        }
        port = atoi(argv[1]);
        sbuf_init(&sbuf, SBUFSIZE);
        listenfd = Open_listenfd(port);
     
        for (i = 0; i < NTHREADS; i++)  /* Create worker threads */
        Pthread_create(&tid, NULL, thread, NULL);
     
        while (1) {
        connfd = Accept(listenfd, (SA *) &clientaddr, &clientlen);
        sbuf_insert(&sbuf, connfd); /* Insert connfd in buffer */
        }
    }
     
    static void init_echo_cnt(void)
    {
        Sem_init(&mutex, 0, 1);
        byte_cnt = 0;
    }
     
    void echo_cnt(int connfd)
    {
        int n,x;
        long int count;
        char buf[MAXLINE];
        char name[MAXLINE]
        rio_t rio;
        static pthread_once_t once = PTHREAD_ONCE_INIT;
     
        Pthread_once(&once, init_echo_cnt);
        Rio_readinitb(&rio, connfd);
        while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
        P(&mutex);
        byte_cnt += n;
            /*x = sizeof(buf);
            buf[x] = 0;
            count = wc(buf);*/
        printf("thread %d received %d (%d total) bytes on fd %d
    ",
               (int) pthread_self(), n, byte_cnt, connfd);
            //name = buf;
        V(&mutex);
            //sprint(buf,"%s:%ld characters".count);
     
        Rio_writen(connfd, buf, n);
        }
    }
     
    void sbuf_init(sbuf_t *sp, int n)
    {
        sp->buf = Calloc(n, sizeof(int));
        sp->n = n;                       /* Buffer holds max of n items */
        sp->front = sp->rear = 0;        /* Empty buffer iff front == rear */
        Sem_init(&sp->mutex, 0, 1);      /* Binary semaphore for locking */
        Sem_init(&sp->slots, 0, n);      /* Initially, buf has n empty slots */
        Sem_init(&sp->items, 0, 0);      /* Initially, buf has zero data items */
    }
    /* $end sbuf_init */
     
    /* Clean up buffer sp */
    /* $begin sbuf_deinit */
    void sbuf_deinit(sbuf_t *sp)
    {
        Free(sp->buf);
    }
    /* $end sbuf_deinit */
     
    /* Insert item onto the rear of shared buffer sp */
    /* $begin sbuf_insert */
    void sbuf_insert(sbuf_t *sp, int item)
    {
        P(&sp->slots);                          /* Wait for available slot */
        P(&sp->mutex);                          /* Lock the buffer */
        sp->buf[(++sp->rear)%(sp->n)] = item;   /* Insert the item */
        V(&sp->mutex);                          /* Unlock the buffer */
        V(&sp->items);                          /* Announce available item */
    }
    /* $end sbuf_insert */
     
    /* Remove and return the first item from buffer sp */
    /* $begin sbuf_remove */
    int sbuf_remove(sbuf_t *sp)
    {
        int item;
        P(&sp->items);                          /* Wait for available item */
        P(&sp->mutex);                          /* Lock the buffer */
        item = sp->buf[(++sp->front)%(sp->n)];  /* Remove the item */
        V(&sp->mutex);                          /* Unlock the buffer */
        V(&sp->slots);                          /* Announce available slot */
        return item;
    }
     
    void *thread(void *vargp)
    { 
        Pthread_detach(pthread_self());
        while (1) {
        int connfd = sbuf_remove(&sbuf); /* Remove connfd from buffer */
        echo_cnt(connfd);                /* Service client */
        Close(connfd);
        }
    }
    

    客户端

    #include "csapp.h"
    #include<stdio.h>
    #include<stdlib.h>
    int wc(char *name)
    {
     char ch;
     FILE *fp;
     long count=0;
     char s[21];
      
      
     if ((fp=fopen("test1.txt","r+"))==NULL)
     {
      fprintf(stderr,"不能打开文件%s
    ",name);
      exit(EXIT_FAILURE);
     }
    while(fscanf(fp,"%s",s)!=EOF)
            count++;
      
     fclose(fp);
     printf("File %s has %ld characters
    ",name,count);
     return 0;
    }
    int main(int argc, char **argv)
    {
        int clientfd, port,n,count;
        char *host, buf[MAXLINE];
        rio_t rio;
     
        if (argc != 3) {
        fprintf(stderr, "usage: %s <host> <port>
    ", argv[0]);
        exit(0);
        }
        host = argv[1];
        port = atoi(argv[2]);
     
        clientfd = Open_clientfd(host, port);
        Rio_readinitb(&rio, clientfd);
     
        while (Fgets(buf, MAXLINE, stdin) != NULL) {
            if((num=recv(sockfd,buf,MAXDATASIZE,0))==-1)
        {
            printf("recv() error
    ");
            exit(1);
        }
        buf[num-1]='';
         
             
        Rio_writen(clientfd, buf, strlen(buf));
        Rio_readlineb(&rio, buf, MAXLINE);
        Fputs(buf, stdout);
        }
        Close(clientfd);
        exit(0);
    }
    /* $end echoclientmain */
    /* $begin echoclientmain */
    //#include "csapp.h"
    /*int main(int argc, char **argv)
    {
        int clientfd, port;
        char *host, buf[MAXLINE];
        char *name;
        rio_t rio;
        FILE *fp;
        if (argc != 4) {
        fprintf(stderr, "usage: %s <host> <port> <filename>
    ", argv[0]);
        exit(0);
        }
        host = argv[1];
        port = atoi(argv[2]);
        name = argv[3];
        clientfd = Open_clientfd(host, port);
        Rio_readinitb(&rio, clientfd);
     
        fp=fopen(name,"r+");
        while (Fgets(buf, MAXLINE,fp) != NULL) {
        Rio_writen(clientfd, buf, strlen(buf));
        Rio_readlineb(&rio, buf, MAXLINE);
        Fputs(buf, stdout);
        }
        Close(clientfd);
        exit(0);
    }
    

    新学到的知识点

    更深入的理解了客户端和服务端

    学习了man查询命令

  • 相关阅读:
    Django通用视图执行过程
    Django HTTP处理流程(自我总结)
    CentOS 安装MySQL5.7
    Python--定时给Ta讲笑话
    【转】对Django框架架构和Request/Response处理流程的分析
    Python模块发布
    Django中使用CKEditor代码高亮显示插件Code Snippet
    页面中的"返回顶部"(位置固定,指定位置显示/隐藏) Label:博客园美化
    跨域请求配置 Amazon AWS S3 腾讯云 阿里云 COS OSS 文件桶解决方案以及推荐 Label:Research
    文件分发服务器 AWS CloudFront(CDN)使用入门-以S3为例 Label:Research
  • 原文地址:https://www.cnblogs.com/wyb-1998/p/9959040.html
Copyright © 2020-2023  润新知