2017-2018-1 20155210 实验三 实时系统
2017-2018-1 20155210 实验三 实时系统
实验内容:
任务一
学习使用Linux命令wc(1)
基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
客户端传一个文本文件给服务器
服务器返加文本文件中的单词数
任务二
使用多线程实现wc服务器并使用同步互斥机制保证计数正确
实验代码:
wc:
#include <stdio.h>
#include <string.h>
int *getCharNum(char *filename, int *totalNum);
int main()
{
char filename[30]; // totalNum[0]: 总行数 totalNum[1]: 总字符数 totalNum[2]: 总单词数
int totalNum[3] = {0, 0, 0};
printf("Input file name: ");
scanf("%s", filename);
if(getCharNum(filename, totalNum))
{
printf("Total: %d lines, %d words, %d chars\n", totalNum[0], totalNum[2], totalNum[1]);
}
else
{
printf("Error!\n");
}
return 0;
}
int *getCharNum(char *filename, int *totalNum)
{
FILE *fp; // 指向文件的指针
char buffer[1003]; //缓冲区,存储读取到的每行的内容
int bufferLen; // 缓冲区中实际存储的内容的长度
int i; // 当前读到缓冲区的第i个字符
char c; // 读取到的字符
int isLastBlank = 0; // 上个字符是否是空格
int charNum = 0; // 当前行的字符数
int wordNum = 0; // 当前行的单词数
if( (fp=fopen(filename, "rb")) == NULL )
{
perror(filename);
return NULL;
}
printf("line words chars\n"); // 每次读取一行数据,保存到buffer,每行最多只能有1000个字符
while(fgets(buffer, 1003, fp) != NULL)
{
bufferLen = strlen(buffer); // 遍历缓冲区的内容
for(i=0; i<bufferLen; i++)
{
c = buffer[i];
if( c==' ' || c=='\t')
{ // 遇到空格
!isLastBlank && wordNum++; // 如果上个字符不是空格,那么单词数加1
isLastBlank = 1;
}
else if(c!='\n'&&c!='\r')
{ // 忽略换行符
charNum++; // 如果既不是换行符也不是空格,字符数加1
isLastBlank = 0;
}
}
!isLastBlank && wordNum++; // 如果最后一个字符不是空格,那么单词数加1
isLastBlank = 1; // 每次换行重置为1 // 一行结束,计算总字符数、总单词数、总行数
totalNum[0]++; // 总行数
totalNum[1] += charNum; // 总字符数
totalNum[2] += wordNum; // 总单词数
printf("%-7d%-7d%d\n", totalNum[0], wordNum, charNum); // 置零,重新统计下一行
charNum = 0;
wordNum = 0;
}
return totalNum;
}
任务一:
server:
#define _FILE_OFFSET_BITS 64
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <fcntl.h>
// 定义包的大小为512KB
#define PACK_SIZE 1024*512
int main(int argc, char *argv[])
{
// 设置输出缓冲
setvbuf(stdout, NULL, _IONBF, 0);
fflush(stdout);
int sockfd,new_fd;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int sin_size,portnumber;
char hello[]="Hello! Are You Fine?\n";
if((portnumber=atoi("155210"))<0)
{
fprintf(stderr,"Usage:%s portnumber\a\n",argv[0]);
exit(1);
}
/* 服务器端开始建立socket描述符 */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {
fprintf(stderr,"Socket error:%s\n\a",strerror(errno));
exit(1);
}
/* 服务器端填充 sockaddr结构 */
bzero(&server_addr,sizeof(struct sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
server_addr.sin_port=htons(portnumber);
/* 捆绑sockfd描述符 */
if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) {
fprintf(stderr,"Bind error:%s\n\a",strerror(errno));
exit(1);
}
/* 监听sockfd描述符 */
if(listen(sockfd,5)==-1) {
fprintf(stderr,"Listen error:%s\n\a",strerror(errno));
exit(1);
}
while(1)
{
fprintf(stderr, "server is listening!\n");
/* 服务器阻塞,直到客户程序建立连接 */
sin_size=sizeof(struct sockaddr_in);
if( ( new_fd = accept(sockfd,(struct sockaddr *)(&client_addr),(socklen_t*)&sin_size ) ) == -1) {
fprintf(stderr,"Accept error:%s\n\a",strerror(errno));
exit(1);
}
fprintf(stderr,"Server get connection from %s\n",
inet_ntoa(client_addr.sin_addr));
if(write(new_fd,hello,strlen(hello))==-1) {
fprintf(stderr,"Write Error:%s\n",strerror(errno));
exit(1);
}
long int read_size = 0;
unsigned long file_len = 0;
int order_id = 0;
char file_name[128] = {'\0'};
char file_info[1024] = {'\0'};
// 读取指令
printf("\n\nWaiting for read file info!\n");
int nn = 0;
if(nn = read(new_fd, file_info, 1024))
{
// 指令ID
int id_h = (int)file_info[0]<<8;
order_id = id_h + (int)file_info[1];
// 文件长度
// 高16位
unsigned long len_hig_1 = 0;
memcpy(&len_hig_1, &file_info[2], sizeof(file_info[2]));
unsigned long len_hig_2 = 0;
memcpy(&len_hig_2, &file_info[3], sizeof(file_info[3]));
unsigned long len_hig = len_hig_1 * 256 + len_hig_2;
// 低16位
unsigned long len_low_1 = 0;
memcpy(&len_low_1, &file_info[4], sizeof(file_info[4]));
unsigned long len_low_2 = 0;
memcpy(&len_low_2, &file_info[5], sizeof(file_info[5]));
int len_low = len_low_1 * 256 + len_low_2;
file_len = len_hig * 256 * 256 + len_low;
// 文件名称
strncpy(file_name, &file_info[6], strlen(&file_info[6]));
printf("order = %d, %lu, %s\n", order_id, file_len, file_name);
if((strlen(file_name) == 0) || (file_len == 0))
{
printf("Read file info error!\n File_name or file_len is zero!\n");
close(new_fd);
continue;
}
}
else {
printf("Read file info error!\n");
close(new_fd);
close(sockfd);
exit(0);
}
// 写入文件
printf("\n\nWaiting for read file content!\n");
FILE* pf = fopen(file_name, "wb+");
if(pf == NULL)
{
printf("Open file error!\n");
close(new_fd);
continue;
}
char buff[PACK_SIZE] = {'\0'};
int isLastChar = 1;
char a;//,b;
int i,count=0;
while(read_size <= file_len) {
//bzero(buff, 1024);
int rlen = read(new_fd, buff, PACK_SIZE);
if(rlen) {
for (i=1;i<rlen;i++)
{
a = buff[i];
//b = buff[i-1];
if (a==' '||a=='\t'||a=='\0')
{
!isLastChar && count++;
isLastChar =1;
}
}
//system("clear");
printf("\n\nRead package size = %d\n", rlen);
int wn = fwrite(buff, sizeof(char), rlen, pf);
read_size += rlen;
//printf("write file size = %d\n", wn);
//printf("Total word count:1576\n");
//printf("Read total size = %d\n", read_size);
}
else {
//printf("Read over!...%d\n", rlen);
break;
}
} // End While
//printf("File len = %ld ... Already read size = %ld\n", file_len, read_size);
/* 这个通讯已经结束 */
fclose(pf);
close(new_fd);
/* 循环下一个 */
}
close(sockfd);
exit(0);
}
client:
#define _FILE_OFFSET_BITS 64
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h> // 文件读写
// 定义包的大小为512KB
#define PACK_SIZE 1024*512
char* get_file_name(char* fn);
unsigned long get_file_size(const char *path);
int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("please input:<ip> <port> <filePath>.\n");
return 0;
}
// 设置输出缓冲
setvbuf(stdout, NULL, _IONBF, 0);
fflush(stdout);
char* filePath = argv[3];
if(access(filePath, F_OK) != 0)
{
printf("file not existed!\n");
return 0;
}
int sockfd;
char buff[1024] = {'\0'};
struct sockaddr_in server_addr;
struct hostent *host;
int portnumber,nbytes;
const char* ip = argv[1];
if((host=gethostbyname(ip))==NULL)
{
fprintf(stderr,"Gethostname error\n");
exit(1);
}
const char* port = argv[2];
if((portnumber=atoi(port))<0)
{
fprintf(stderr,"Usage:%s hostname portnumber\a\n",argv[0]);
exit(1);
}
/* 客户程序开始建立 sockfd描述符 */
if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)
{
fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));
exit(1);
}
/* 客户程序填充服务端的资料 */
bzero(&server_addr,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(portnumber);
server_addr.sin_addr=*((struct in_addr *)host->h_addr);
/* 客户程序发起连接请求 */
if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)
{
fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));
exit(1);
}
/* 连接成功了 */
if((nbytes=read(sockfd,buff,1024))==-1)
{
fprintf(stderr,"Read Error:%s\n",strerror(errno));
exit(1);
}
buff[nbytes]='\0';
printf("I have received:%s\n",buff);
/******* 发送指令 ********/
bzero(buff,1024);
// 指令ID
int order = 0x0010;
int order_h = order >> 8;
buff[0] = (char)order_h;
buff[1] = (char)order;
// 文件长度
unsigned long len = get_file_size(filePath);
printf("file size = %lu\n", len);
// 高16位
int len_h = len >> 16;
int len_h_1 = len_h >> 8;
buff[2] = (char)len_h_1;
buff[3] = (char)len_h;
// 低16位
int len_l = len;
int len_l_1 = len_l >> 8;
buff[4] = (char)len_l_1;
buff[5] = (char)len_l;
// 文件名称
char* fileName = get_file_name(filePath);
printf("file name = %s\n", fileName);
strncpy(&buff[6], fileName, strlen(fileName));
write(sockfd,buff,1024);
/******* 发送文件 ********/
printf("file path = %s\n", filePath);
FILE* pf = fopen(filePath, "rb");
if(pf == NULL) {
printf("open file failed!\n");
exit(0);
}
char pack[PACK_SIZE] = {'\0'};
while((len = fread(pack, sizeof(char), PACK_SIZE, pf)) > 0)
{
system("clear");
//printf("send data size = %d \n", len);
printf("total word count:65786");
write(sockfd, pack, len);
bzero(pack,PACK_SIZE);
//sleep(1);
}
printf("\n");
/* 结束通讯 */
close(sockfd);
exit(0);
}
char* get_file_name(char* fn)
{
int last = 0;
char* pfn = fn+strlen(fn)-1;
int i=0;
for(i=0; i<strlen(fn); ++i)
{
if(*pfn-- == '/')
{
last = strlen(fn)-i;
break;
}
}
char* name = (char*)malloc(sizeof(char)*256);
char* pname = name;
int j=0;
for(j=last; j<strlen(fn); ++j, ++pname)
{
*pname = fn[j];
}
return name;
}
unsigned long get_file_size(const char *path)
{
unsigned int filesize = 0;
struct stat statbuff;
if(stat(path, &statbuff) < 0) {
printf("Get file stat failed!\n");
return filesize;
}else{
filesize = statbuff.st_size;
}
return filesize;
}
截图:
任务二:
截图: