2017-2018-1 20155209 實驗三 實時系統
阿新 • • 發佈:2017-11-20
基於 文本文 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(<); 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(<);
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 實驗三 實時系統