2017-2018-1 20155320 实验三——实时系统
实验三-并发程序-1
学习使用Linux命令wc(1)
基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的>后6位)和客户端
客户端传一个文本文件给服务器
服务器返加文本文件中的单词数
上方提交代码
附件提交测试截图,至少要测试附件中的两个文件
- 学习使用Linux命令wc(1)
命令格式:wc [选项]文件..
-c 统计字节数。
-l 统计行数。
-m 统计字符数。这个标志不能与 -c 标志一起使用。
-w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。
-L 打印最长行的长度。
我的mywc的实现:
#include<stdio.h>
#include<unistd.h>
#include<sys/stat.h>
#include<stdlib.h>
struct message{
int lines;
int words;
int max_line_length;
int size;
int chars;
}info;
void error_print(char str[]){
printf("Error:%s",str);
}
void init(char filename[]){
struct stat get_message = {};
FILE *fp;
int ret_stat = stat(filename,&get_message);/*用stat函数读取filenmae文件的信息,并将结果写到get_message结构体中*/
if(ret_stat == -1){//stat函数不出错则进行信息输出
error_print(filename);
return ;
}
mode_t mode = get_message.st_mode; //接收文件信息,用于下面判断是不是目录
int length = 0;
if(S_ISDIR(mode)) //如果是目录,输出错误
printf("Error %s is dir\n0\t0\t0\t%s",filename,filename);
else{
info.size = get_message.st_size; //文件字节大小 wc -c
fp = fopen(filename,"r"); //以只读方式打开指定文件
char ch;
int flag = 0;
while((ch = fgetc(fp))!=EOF){ //一直读到文件尾
info.chars++; //字符数加1 wc -m
if(ch != '\n'){
length++; //记录当前行的长度 wc -L
}
if(ch == '\n'){
info.lines ++; //行数加1 wc -l
if(length>info.max_line_length)
info.max_line_length = length; //更新最大长度
length = 0;
}
if(ch == '\t' || ch == ' ' || ch == '\n'){
flag = 0; //计算单词数 wc -w
continue;
}
else{
if(flag == 0){
info.words++; //计算单词数 wc -w
flag = 1;
}
}
}
fclose(fp);
}
}
//计算键盘输入内容的相关信息,即参数中没有指定要打开的文件
void EmptyFile(){
char ch;
int flag = 0;
int length = 0;
while((ch = getchar())!=EOF){
info.chars++;
info.size += sizeof(ch); //字节累加
if(ch != '\n'){
length++;
}
if(ch == '\n'){
info.lines ++;
if(length>info.max_line_length)
info.max_line_length = length;
length = 0;
}
if(ch == '\t' || ch == ' ' || ch == '\n'){
flag = 0;
continue;
}
else{
if(flag == 0){
info.words++;
flag = 1;
}
}
}
}
int main(int argc,char *argv[]){
if(argc == 2){
if(argv[1][0] != '-'){
init(argv[1]);
printf("%d %d %d %s\n",info.lines,info.words,info.size,argv[1]);
return 0;
}
else{ //未指定打开文件,类似 wc -lmwcL
EmptyFile();
}
}
else if(argc == 1){ //未指定打开文件和要输出的参数,(默认输出 -lwc)
EmptyFile();
printf("%d\t%d\t%d\n",info.lines,info.words,info.size);
return 0;
}
else if(argc == 3){
init(argv[2]);
}
int num;
while((num = getopt(argc,argv,"lwmcL"))!=-1){
switch(num){
case 'l':
printf("%d\t",info.lines);
break;
case 'w':
printf("%d\t",info.words);
break;
case 'm':
printf("%d\t",info.chars);
break;
case 'c':
printf("%d\t",info.size);
break;
case 'L':
printf("%d\t",info.max_line_length);
break;
}
}
if(argc != 2 && argv[1][0] != '-') //一定要判断,否则会越界
printf("%s\n",argv[2]);
return 0;
}
-
wc的测试
-
客户端与服务器运行结果截图如下
实验三-并发程序-2
使用多线程实现wc服务器并使用同步互斥机制保证计数正确
对比单线程版本的性能,并分析原因
- 运行截图如下:
-
对比单线程版本的性能,并分析原因
并发的程序相对单线程版本来说最直观的特点就是其可以实现一个服务器连接多个客户端,这是单线程版本无法做到的,可见相较单线程版本来说更加完善
实现中遇到的问题
-
问题:代码完成后,mywc统计字符数是对的,但是客户端显示的却不对
-
解决:用cbd调试代码,先不打印,发现用来存储字节的buff数组末尾没有\0,因此不会被看成字符串输出,修改代码后,则运行成功了