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>
",argv[0]);
exit(0);
}
host = argv[1];
port = atoi(argv[2]);
clientfd = open_clientfd(host,port);
while(1){
printf("输入文件名(.txt):
");
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('
');
//printf("%s",str3);
//puts(rbuf);
fclose(fp);
//sleep(1000);
//recv(clientfd,rbuf,MAXLINE,0);
//printf("传输完成,该文件单词数为%s
!",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
",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] = ' ';
}
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>
",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)
",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
",recv(connfd,rbuf,MAXLINE,0));
fputs(rbuf,fp);
bzero(rbuf,sizeof(rbuf));
count += cnt;
}
//printf("传输成功!,该文件单词数共%d
!",count);
fclose(fp);
itoa(count,sbuf);
//send(connfd,sbuf,MAXLINE,0);
printf("该文件单词数为%s!
",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>
",argv[0]);
exit(0);
}
host = argv[1];
port = atoi(argv[2]);
clientfd = open_clientfd(host,port);
while(1){
printf("输入文件名(.txt):
");
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('
');
//printf("%s",str3);
//puts(rbuf);
fclose(fp);
//sleep(1000);
//recv(clientfd,rbuf,MAXLINE,0);
//printf("传输完成,该文件单词数为%s
!",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>
",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)
",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
",recv(connfd,rbuf,MAXLINE,0));
fputs(rbuf,fp);
bzero(rbuf,sizeof(rbuf));
count += cnt;
}
//printf("传输成功!,该文件单词数共%d
!",count);
fclose(fp);
itoa(count,sbuf);
//send(connfd,sbuf,MAXLINE,0);
printf("该文件单词数为%s!
",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] = ' ';
}
-
程序运行结果截图:
-
实验中遇到的问题:在自己电脑(Mac)运行代码出现如下问题:Static library link issue with Mac OS X: symbol(s) not found for architecture x86_64。
-
解决方法:在网上寻找了许多方法都不能编译成功。最后在Mac里安装了Linux虚拟机,在虚拟机里做这个实验了。