2017-2018-1 20155212 实验三 实时系统

本文介绍了一个基于 Linux Socket 的 wc 命令实现案例,包括单线程和多线程版本,用于统计从客户端接收的文本文件中的单词数量。

2017-2018-1 20155212 实验三 实时系统

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

题目

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

步骤

  • 使用man wc命令查看wc1043723-20171119105509546-1687837329.png
  • wc命令详解
    • 语法:wc [选项] 文件
    • 选项含义
      • c:统计字节数
      • l:统计行数
      • w:统计字数
  • 使用示例1043723-20171119111215937-510935453.png
  • 实现难点:
    • 如何统计单词数?
      • 使用od -tc命令查看文本中单词之间如何间隔1043723-20171119111554015-1475327618.png
      • 单词间通过' '、'\r'、'\n'间隔开
    • 统计结果与实际出现较大误差
      • 字符间可能有多个间隔符,因此连续的间隔符只能算一个

最终代码

  • 服务器

    /*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 155212
    
    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\n", 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 '\n':
                                    wordscount++;
                                    break;
                                case '\r':
                                    wordscount++;
                                    break;
                                default:
                                    break;
                            }
                        }
                        if(buffer[i]== ' ' || buffer[i]=='\n' || buffer[i]=='\r') flag=1;
                        else flag=0;
                    }
                }
                if(len<1024) break;
            }
            send(clientfd, &wordscount, sizeof(long), 0);
            close(clientfd);
        }
        close(serverfd);
    }
  • 客户端
    ```
    /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 155212

    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\n", wordscount);
      close(clientfd);
    }
    ```
  • 运行结果截图1043723-20171119111956484-1244429725.png

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

分析

  • 1中的客户端代码不需要改变,只需要改变服务器代码即可。
  • 服务器代码需要增加两个功能
    • 增加多线程
    • 使用同步互斥

代码

  • 服务器
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <pthread.h>

#define MYPORT 155212
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;

char buffer[BUFSIZ];
void *wc(void *m){
    pthread_mutex_lock( &counter_mutex );
    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 '\n':
                            wordscount++;
                            break;
                        case '\r':
                            wordscount++;
                            break;
                        default:
                            break;
                    }
                }
                if(buffer[i]== ' ' || buffer[i]=='\n' || buffer[i]=='\r') flag=1;
                else flag=0;
            }
        }
        if(len<1024) break;
    }
    send(clientfd, &wordscount, sizeof(long), 0);
    close(clientfd);
    pthread_mutex_unlock( &counter_mutex );
    return NULL;
}
void main(){
    pthread_t t;    
    char arg[30];
    int serverfd, clientfd;
    struct sockaddr_in my_addr;
    struct sockaddr_in remote_addr;

    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family=AF_INET;
    my_addr.sin_addr.s_add#include  <pthread.h>r=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\n", inet_ntoa(remote_addr.sin_addr));
        pthread_create(&t, NULL, &wc, NULL);
        pthread_join(&t, NULL);
    }
    close(serverfd);
}

运行结果

1043723-20171119113518702-1246715548.png

实验总结

  • 在本次实验中,实验进展比较慢,主要原因在于对socket编程不够熟悉,有一些错误一直没调出来,而且由于比较急,任务二的截图提交错了。在今后的实验中,需要更加提前准备实验,同时在提交截图时需要仔细确认。
  • 希望老师能多提前几天将其他实验的任务给我们,以便我们能充分准备好实验

转载于:https://www.cnblogs.com/dky20155212/p/7859380.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值