2017-2018-1 20155317实验三 实时系统报告
2017-2018-1 20155317 实验三 实时系统报告
学习wc命令:
使用man命令查看
wc是返回当前文档的单词数量
实验一
基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
客户端传一个文本文件给服务器
服务器返加文本文件中的单词数
client:
#include<netinet/in.h> // sockaddr_in
#include<sys/types.h> // socket
#include<sys/socket.h> // socket
#include<stdio.h> // printf
#include<stdlib.h> // exit
#include<string.h> // bzero
#define SERVER_PORT 5317
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
int main()
{
struct sockaddr_in client_addr;
bzero(&client_addr, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = htons(INADDR_ANY);
client_addr.sin_port = htons(0);
int client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(client_socket_fd < 0)
{
perror("Create Socket Failed:");
exit(1);
}
if(-1 == (bind(client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr))))
{
perror("Client Bind Failed:");
exit(1);
}
struct sockaddr_in server_addr;
bzero(&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
if(inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) == 0)
{
perror("Server IP Address Error:");
exit(1);
}
server_addr.sin_port = htons(SERVER_PORT);
socklen_t server_addr_length = sizeof(server_addr);
if(connect(client_socket_fd, (struct sockaddr*)&server_addr, server_addr_length) < 0)
{
perror("Can Not Connect To Server IP:");
exit(0);
}
char file_name[FILE_NAME_MAX_SIZE+1];
bzero(file_name, FILE_NAME_MAX_SIZE+1);
printf("Please Input File Name On Server:\t");
scanf("%s", file_name);
char buffer[BUFFER_SIZE];
bzero(buffer, BUFFER_SIZE);
strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name));
if(send(client_socket_fd, buffer, BUFFER_SIZE, 0) < 0)
{
perror("Send File Name Failed:");
exit(1);
}
FILE *fp = fopen(file_name, "w");
if(NULL == fp)
{
printf("File:\t%s Can Not Open To Write\n", file_name);
exit(1);
}
bzero(buffer, BUFFER_SIZE);
int length = 0;
while((length = recv(client_socket_fd, buffer, BUFFER_SIZE, 0)) > 0)
{
if(fwrite(buffer, sizeof(char), length, fp) < length)
{
printf("File:\t%s Write Failed\n", file_name);
break;
}
bzero(buffer, BUFFER_SIZE);
}
printf("Send File:\t%s Successful!\n", file_name);
close(fp);
close(client_socket_fd);
char *argv[]={"wc","-w",file_name,0};
execvp("wc",argv);
return 0;
}
server:
#include<netinet/in.h> // sockaddr_in #include<sys/types.h> // socket #include<sys/socket.h> // socket #include<stdio.h> // printf #include<stdlib.h> // exit #include<string.h> // bzero #define SERVER_PORT 8000 #define LENGTH_OF_LISTEN_QUEUE 20 #define BUFFER_SIZE 1024 #define FILE_NAME_MAX_SIZE 512 int main(void) { // 声明并初始化一个服务器端的socket地址结构 struct sockaddr_in server_addr; bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htons(INADDR_ANY); server_addr.sin_port = htons(SERVER_PORT); // 创建socket,若成功,返回socket描述符 int server_socket_fd = socket(PF_INET, SOCK_STREAM, 0); if(server_socket_fd < 0) { perror("Create Socket Failed:"); exit(1); } int opt = 1; setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // 绑定socket和socket地址结构 if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)))) { perror("Server Bind Failed:"); exit(1); } // socket监听 if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE))) { perror("Server Listen Failed:"); exit(1); } while(1) { struct sockaddr_in client_addr; socklen_t client_addr_length = sizeof(client_addr); int new_server_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &client_addr_length); if(new_server_socket_fd < 0) { perror("Server Accept Failed:"); break; } char buffer[BUFFER_SIZE]; bzero(buffer, BUFFER_SIZE); if(recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0) < 0) { perror("Server Recieve Data Failed:"); break; } char file_name[FILE_NAME_MAX_SIZE+1]; bzero(file_name, FILE_NAME_MAX_SIZE+1); strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer)); printf("%s\n", file_name); FILE *fp = fopen(file_name, "r"); if(NULL == fp) { printf("File:%s Not Found\n", file_name); } else { bzero(buffer, BUFFER_SIZE); int length = 0; while((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0) { if(send(new_server_socket_fd, buffer, length, 0) < 0) { printf("Send File:%s Failed./n", file_name); break; } bzero(buffer, BUFFER_SIZE); } fclose(fp); printf("File:%s Transfer Successful!\n", file_name); } // 关闭与客户端的连接 close(new_server_socket_fd); } // 关闭监听用的socket close(server_socket_fd); return 0; }
实验二:
- 多线程实现wc服务器时,会出现多个客户端同时像服务器传送文件的情况,所以仅仅在服务器端创建一个recvfile.txt用于接收文件是远远不够的,需要根据发送的不同文件名创建新的接收文件。
client:
#include "csapp.h" #include<stdio.h> #include<stdlib.h> int wc(char *name) { char ch; FILE *fp; long count=0; char s[21]; if ((fp=fopen("test1.txt","r+"))==NULL) { fprintf(stderr,"不能打开文件%s\n",name); exit(EXIT_FAILURE); } while(fscanf(fp,"%s",s)!=EOF) count++; fclose(fp); printf("File %s has %ld characters\n",name,count); return 0; } int main(int argc, char **argv) { int clientfd, port,n,count; char *host, buf[MAXLINE]; rio_t rio; 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); Rio_readinitb(&rio, clientfd); while (Fgets(buf, MAXLINE, stdin) != NULL) { if((num=recv(sockfd,buf,MAXDATASIZE,0))==-1) { printf("recv() error\n"); exit(1); } buf[num-1]='\0'; Rio_writen(clientfd, buf, strlen(buf)); Rio_readlineb(&rio, buf, MAXLINE); Fputs(buf, stdout); } Close(clientfd); exit(0); } /* $end echoclientmain */ /* $begin echoclientmain */ //#include "csapp.h" /*int main(int argc, char **argv) { int clientfd, port; char *host, buf[MAXLINE]; char *name; rio_t rio; FILE *fp; if (argc != 4) { fprintf(stderr, "usage: %s <host> <port> <filename>\n", argv[0]); exit(0); } host = argv[1]; port = atoi(argv[2]); name = argv[3]; clientfd = Open_clientfd(host, port); Rio_readinitb(&rio, clientfd); fp=fopen(name,"r+"); while (Fgets(buf, MAXLINE,fp) != NULL) { Rio_writen(clientfd, buf, strlen(buf)); Rio_readlineb(&rio, buf, MAXLINE); Fputs(buf, stdout); } Close(clientfd); exit(0); }
server:
#include "csapp.h" #include<stdio.h> #include<stdlib.h> static int byte_cnt; /* byte counter */ static sem_t mutex; #define NTHREADS 4 #define SBUFSIZE 16 typedef struct { int *buf; /* Buffer array */ int n; /* Maximum number of slots */ int front; /* buf[(front+1)%n] is first item */ int rear; /* buf[rear%n] is last item */ sem_t mutex; /* Protects accesses to buf */ sem_t slots; /* Counts available slots */ sem_t items; /* Counts available items */ } sbuf_t; void echo_cnt(int connfd); void *thread(void *vargp); int wc(char *name) { char ch; FILE *fp; long count=0; char s[21]; if ((fp=fopen(name,"r+"))==NULL) { fprintf(stderr,"不能打开文件\n"); exit(EXIT_FAILURE); } while(fscanf(fp,"%s",s)!=EOF) count++; fclose(fp); printf("File %s has %ld characters\n",name,count); return 0; } sbuf_t sbuf; /* shared buffer of connected descriptors */ int main(int argc, char **argv) { int i, listenfd, connfd, port, clientlen=sizeof(struct sockaddr_in); struct sockaddr_in clientaddr; pthread_t tid; if (argc != 2) { fprintf(stderr, "usage: %s <port>\n", argv[0]); exit(0); } port = atoi(argv[1]); sbuf_init(&sbuf, SBUFSIZE); listenfd = Open_listenfd(port); for (i = 0; i < NTHREADS; i++) /* Create worker threads */ Pthread_create(&tid, NULL, thread, NULL); while (1) { connfd = Accept(listenfd, (SA *) &clientaddr, &clientlen); sbuf_insert(&sbuf, connfd); /* Insert connfd in buffer */ } } static void init_echo_cnt(void) { Sem_init(&mutex, 0, 1); byte_cnt = 0; } void echo_cnt(int connfd) { int n,x; long int count; char buf[MAXLINE]; char name[MAXLINE] rio_t rio; static pthread_once_t once = PTHREAD_ONCE_INIT; Pthread_once(&once, init_echo_cnt); Rio_readinitb(&rio, connfd); while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) { P(&mutex); byte_cnt += n; /*x = sizeof(buf); buf[x] = 0; count = wc(buf);*/ printf("thread %d received %d (%d total) bytes on fd %d\n", (int) pthread_self(), n, byte_cnt, connfd); //name = buf; V(&mutex); //sprint(buf,"%s:%ld characters".count); Rio_writen(connfd, buf, n); } } void sbuf_init(sbuf_t *sp, int n) { sp->buf = Calloc(n, sizeof(int)); sp->n = n; /* Buffer holds max of n items */ sp->front = sp->rear = 0; /* Empty buffer iff front == rear */ Sem_init(&sp->mutex, 0, 1); /* Binary semaphore for locking */ Sem_init(&sp->slots, 0, n); /* Initially, buf has n empty slots */ Sem_init(&sp->items, 0, 0); /* Initially, buf has zero data items */ } /* $end sbuf_init */ /* Clean up buffer sp */ /* $begin sbuf_deinit */ void sbuf_deinit(sbuf_t *sp) { Free(sp->buf); } /* $end sbuf_deinit */ /* Insert item onto the rear of shared buffer sp */ /* $begin sbuf_insert */ void sbuf_insert(sbuf_t *sp, int item) { P(&sp->slots); /* Wait for available slot */ P(&sp->mutex); /* Lock the buffer */ sp->buf[(++sp->rear)%(sp->n)] = item; /* Insert the item */ V(&sp->mutex); /* Unlock the buffer */ V(&sp->items); /* Announce available item */ } /* $end sbuf_insert */ /* Remove and return the first item from buffer sp */ /* $begin sbuf_remove */ int sbuf_remove(sbuf_t *sp) { int item; P(&sp->items); /* Wait for available item */ P(&sp->mutex); /* Lock the buffer */ item = sp->buf[(++sp->front)%(sp->n)]; /* Remove the item */ V(&sp->mutex); /* Unlock the buffer */ V(&sp->slots); /* Announce available slot */ return item; } void *thread(void *vargp) { Pthread_detach(pthread_self()); while (1) { int connfd = sbuf_remove(&sbuf); /* Remove connfd from buffer */ echo_cnt(connfd); /* Service client */ Close(connfd); } }