1. 程式人生 > >2017-2018-1 20155209 實驗三 實時系統

2017-2018-1 20155209 實驗三 實時系統

基於 文本文 sel day 虛擬 filename 提交代碼 inux rar

2017-2018-1 20155209 實驗三 實時系統

學習使用Linux命令wc(1)

基於Linux Socket程序設計實現wc(1)服務器(端口號是你學號的後6位)和客戶端
客戶端傳一個文本文件給服務器
服務器返加文本文件中的單詞數

  • 使用man 1 wc查看wc
  • 代碼實現如下:
  • 客戶端
#include <stdio.h>
#include <netinet/in.h>                                                                   
#include <arpa/inet.h>
#include <netdb.h>    
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>

#define RIO_BUFSIZE 8192

typedef struct{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];

}rio_t;

#define MAXLINE 200

int main(int argc,char **argv){

    int clientfd,port;
    char *host,buf[MAXLINE];
    char sbuf[MAXLINE];
    char rbuf[MAXLINE];
    rio_t rio;
    char str1[MAXLINE]="客戶端IP:";
    char str2[MAXLINE]="服務器實現者學號:20155209”;
    
    char str3[MAXLINE]="當地時間:";

    FILE *fp;

    char filename[MAXLINE];


    if(argc!=3){
    
        fprintf(stderr,"usage:%s <host> <port>\n",argv[0]);
        exit(0);
    }
    host = argv[1];
    port = atoi(argv[2]);

    clientfd = open_clientfd(host,port);
  
    while(1){

        printf("輸入文件名(.txt):\n");

        gets(filename);

        fp = fopen(filename,"rb");

        while(!feof(fp)){

        fgets(sbuf,MAXLINE,fp);
        
        send(clientfd,sbuf,MAXLINE,0);

        bzero(sbuf,sizeof(sbuf));       
        }
       

        printf("%s",str1);
        puts(host);

        printf("%s",str2);
        putchar(‘\n‘);

        //printf("%s",str3);
      
        //puts(rbuf);

        fclose(fp);

        //sleep(1000);

        //recv(clientfd,rbuf,MAXLINE,0);

        //printf("傳輸完成,該文件單詞數為%s\n!",rbuf);

        //puts(rbuf);

        close(clientfd);
       
        exit(0);
    }

}

  • 服務器

#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>                                                                   
#include <arpa/inet.h>
#include <netdb.h>    
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define MAXLINE 200
#define RIO_BUFSIZE 8192

typedef struct{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];

}rio_t;

typedef struct sockaddr SA;

typedef struct{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
}tm;

void sigchld_handler(int sig){

    pid_t pid;
    int stat;

    while((pid = waitpid(-1,&stat,WNOHANG))>0){
        printf("child %d terminated\n",pid);
    }
    return;
}

void itoa (int n,char s[])
{
    int i,j,sign;
    char temp[MAXLINE];

    if((sign=n)<0)//記錄符號
        n=-n;//使n成為正數
    i=0;
    do{
               temp[i++]=n%10+‘0‘;//取下一個數字
    }
    while ((n/=10)>0);//刪除該數字
    if(sign<0)
        temp[i++]=‘-‘;

    for(j=0;j<i;j++){//生成的數字是逆序的,所以要逆序輸出
        s[j] = temp[i-j-1];
    }
    s[i] = ‘\0‘;
} 

int main(int argc,char **argv){

    int count=0,cnt=0,listenfd,connfd,port,clientlen;
    struct sockaddr_in clientaddr;
    struct hostent *hp;
    char *haddrp;
    char sbuf[MAXLINE];
   // char *bufp = sbuf;
    char rbuf[MAXLINE];
    rio_t rio;
    time_t lt;
    tm *local;
    char str1[MAXLINE]="客戶端IP:";
    char str2[MAXLINE]="服務器實現者學號:";
    char str3[MAXLINE]="當地時間:";

    FILE *fp = fopen("test.txt","wb");

    if(argc != 2){
    
        fprintf(stderr,"usage:%s <port>\n",argv[0]);
        exit(0);
    }

    port = atoi(argv[1]);

    signal(SIGCHLD,sigchld_handler);
    listenfd = open_listenfd(port);
    while(1){
    
        clientlen = sizeof(clientaddr);
        connfd = accept(listenfd,(SA *)&clientaddr,&clientlen);

        hp = gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
                sizeof(clientaddr.sin_addr.s_addr),AF_INET);
        haddrp = inet_ntoa(clientaddr.sin_addr);
        printf("server connected to %s (%s)\n",hp->h_name,haddrp);

        
        if(fork() == 0){
        close(listenfd);
        

        /*
        lt = time(NULL); 
        local = localtime(&lt);
        strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
        */

        while(cnt = recv(connfd,rbuf,MAXLINE,0)){

        //printf("%d\n",recv(connfd,rbuf,MAXLINE,0));   
        fputs(rbuf,fp);
        bzero(rbuf,sizeof(rbuf));

        count += cnt;
        }

        //printf("傳輸成功!,該文件單詞數共%d\n!",count);

        fclose(fp);

        itoa(count,sbuf);

        //send(connfd,sbuf,MAXLINE,0);
       
        printf("該文件單詞數為%s!\n",sbuf);

        close(connfd);
        exit(0);
        }
        

        close(connfd);
    }
}
  • 實現截圖:
  • 技術分享圖片

使用多線程實現wc服務器並使用同步互斥機制保證計數正確

上方提交代碼
下方提交測試
對比單線程版本的性能,並分析原因

  • 代碼實現如下:
  • 客戶端

#include <stdio.h>
#include <netinet/in.h>                                                                   
#include <arpa/inet.h>
#include <netdb.h>    
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>

#define RIO_BUFSIZE 8192

typedef struct{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];

}rio_t;

#define MAXLINE 200

int main(int argc,char **argv){

    int clientfd,port;
    char *host,buf[MAXLINE];
    char sbuf[MAXLINE];
    char rbuf[MAXLINE];
    rio_t rio;
    char str1[MAXLINE]="客戶端IP:";
    char str2[MAXLINE]="服務器實現者學號:20155209”;
    
    char str3[MAXLINE]="當地時間:";

    FILE *fp;

    char filename[MAXLINE];


    if(argc!=3){
    
        fprintf(stderr,"usage:%s <host> <port>\n",argv[0]);
        exit(0);
    }
    host = argv[1];
    port = atoi(argv[2]);

    clientfd = open_clientfd(host,port);
  
    while(1){

        printf("輸入文件名(.txt):\n");

        gets(filename);

        fp = fopen(filename,"rb");

        while(!feof(fp)){

        fgets(sbuf,MAXLINE,fp);
        
        send(clientfd,sbuf,MAXLINE,0);

        bzero(sbuf,sizeof(sbuf));       
        }
       

        printf("%s",str1);
        puts(host);

        printf("%s",str2);
        putchar(‘\n‘);

        //printf("%s",str3);
      
        //puts(rbuf);

        fclose(fp);

        //sleep(1000);

        //recv(clientfd,rbuf,MAXLINE,0);

        //printf("傳輸完成,該文件單詞數為%s\n!",rbuf);

        //puts(rbuf);

        close(clientfd);
       
        exit(0);
    }

}
  • 服務器
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>                                                                   
#include <arpa/inet.h>
#include <netdb.h>    
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>

#define MAXLINE 200
#define RIO_BUFSIZE 8192

typedef struct{
    int rio_fd;
    int rio_cnt;
    char *rio_bufptr;
    char rio_buf[RIO_BUFSIZE];

}rio_t;

typedef struct sockaddr SA;

typedef struct{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
}tm;



void itoa (int n,char s[]);

void *thread(void *vargp);

int main(int argc,char **argv){

    int listenfd,*connfdp,port;
    int clientlen;
    struct sockaddr_in clientaddr;
    struct hostent *hp;
    char *haddrp;
    pthread_t tid;

    if(argc != 2){
    
        fprintf(stderr,"usage:%s <port>\n",argv[0]);
        exit(0);
    }

    port = atoi(argv[1]);

    listenfd = open_listenfd(port);
    
    
    while(1){
    
        clientlen = sizeof(clientaddr);

        connfdp =malloc(sizeof(int));
    
        *connfdp = accept(listenfd,(SA *)&clientaddr,&clientlen);


        hp = gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
                sizeof(clientaddr.sin_addr.s_addr),AF_INET);

        haddrp = inet_ntoa(clientaddr.sin_addr);

        printf("server connected to %s (%s)\n",hp->h_name,haddrp);

        pthread_create(&tid,NULL,thread,connfdp);

        pthread_join(tid,NULL);
    }
}


void *thread(void *vargp){
    
    time_t lt;
    tm *local;
    char sbuf[MAXLINE];
    int cnt = 0,count = 0;
    char *fp = fopen("test.txt","wb");
    char rbuf[MAXLINE];
    int connfd = *((int*)vargp);

    free(vargp);

    pthread_detach(pthread_self());

    /*lt = time(NULL); 
    local = localtime(&lt);
    strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
    send(connfd,sbuf,MAXLINE,0);
    */
while(cnt = recv(connfd,rbuf,MAXLINE,0)){

        //printf("%d\n",recv(connfd,rbuf,MAXLINE,0));   
        fputs(rbuf,fp);
        bzero(rbuf,sizeof(rbuf));

        count += cnt;
        }


        //printf("傳輸成功!,該文件單詞數共%d\n!",count);

        fclose(fp);

        itoa(count,sbuf);

        //send(connfd,sbuf,MAXLINE,0);
       
        printf("該文件單詞數為%s!\n",sbuf);

    close(connfd);
    
    return NULL;
}


void itoa (int n,char s[])
{
    int i,j,sign;
    char temp[MAXLINE];

    if((sign=n)<0)//記錄符號
        n=-n;//使n成為正數
    i=0;
    do{
               temp[i++]=n%10+‘0‘;//取下一個數字
    }
    while ((n/=10)>0);//刪除該數字
    if(sign<0)
        temp[i++]=‘-‘;

    for(j=0;j<i;j++){//生成的數字是逆序的,所以要逆序輸出
        s[j] = temp[i-j-1];
    }
    s[i] = ‘\0‘;
} 
  • 程序運行結果截圖:
  • 技術分享圖片

  • 實驗中遇到的問題:在自己電腦(Mac)運行代碼出現如下問題:Static library link issue with Mac OS X: symbol(s) not found for architecture x86_64。
  • 解決方法:在網上尋找了許多方法都不能編譯成功。最後在Mac裏安裝了Linux虛擬機,在虛擬機裏做這個實驗了。

2017-2018-1 20155209 實驗三 實時系統