• 2017-2018-1 20155212 实验三 实时系统


    2017-2018-1 20155212 实验三 实时系统

    1 学习使用Linux命令wc(1)

    题目

    • 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
    • 客户端传一个文本文件给服务器
    • 服务器返加文本文件中的单词数

    步骤

    • 使用man wc命令查看wc
    • wc命令详解
      • 语法:wc [选项] 文件
      • 选项含义
        • c:统计字节数
        • l:统计行数
        • w:统计字数
    • 使用示例
    • 实现难点:
      • 如何统计单词数?
        • 使用od -tc命令查看文本中单词之间如何间隔
        • 单词间通过' '、' '、' '间隔开
      • 统计结果与实际出现较大误差
        • 字符间可能有多个间隔符,因此连续的间隔符只能算一个

    最终代码

    • 服务器

      /*server*/
      #include <stdio.h>
      #include <sys/types.h>
      #include <sys/socket.h>
      #include <netinet/in.h>
      #include <arpa/inet.h>
      #include <string.h>
      
      #define MYPORT 155212
      
      void main(){
      	int serverfd, clientfd;
      	struct sockaddr_in my_addr;
      	struct sockaddr_in remote_addr;
      
      	char buffer[BUFSIZ];
      	memset(&my_addr, 0, sizeof(my_addr));
      	my_addr.sin_family=AF_INET;
      	my_addr.sin_addr.s_addr=INADDR_ANY;
      	my_addr.sin_port=htons(MYPORT);
      
      	if((serverfd=socket(PF_INET, SOCK_STREAM, 0))==-1){
      		perror("socket");
      	}
      
      	if(bind(serverfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))<0){
      		perror("bind");
      	}
      	listen(serverfd, 5);
      	int addrlen=sizeof(struct sockaddr_in);	
      	while(1){
      		if((clientfd=accept(serverfd, (struct sockaddr *)&remote_addr, &addrlen))<0){
      			perror("accept");
      		}
      		printf("accept client %s
      ", inet_ntoa(remote_addr.sin_addr));
      		int len, i;
      		long wordscount=0;
      		int flag=1;
      		while(1){
      			if((len=recv(clientfd, buffer, 1024, 0))>0){
      				for(i=0; i<len; i++){
      					if(flag==0){
      						switch(buffer[i]){
      							case ' ':
      								wordscount++;
      								break;
      							case '
      ':
      								wordscount++;
      								break;
      							case '
      ':
      								wordscount++;
      								break;
      							default:
      								break;
      						}
      					}
      					if(buffer[i]== ' ' || buffer[i]=='
      ' || buffer[i]=='
      ') flag=1;
      					else flag=0;
      				}
      			}
      			if(len<1024) break;
      		}
      		send(clientfd, &wordscount, sizeof(long), 0);
      		close(clientfd);
      	}
      	close(serverfd);
      }
      
    • 客户端

      /*client*/
      #include <stdio.h>  
      #include <sys/types.h>  
      #include <sys/socket.h>  
      #include <netinet/in.h>  
      #include <arpa/inet.h>  
      #include <string.h>
      
      #define MYPORT 155212
      
      void main(){
      	int clientfd;
      	struct sockaddr_in remote_addr;
      	char buffer[BUFSIZ];
      	memset(&remote_addr, 0 , sizeof(remote_addr));
      	remote_addr.sin_family=AF_INET;
      	remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
      	remote_addr.sin_port=htons(MYPORT);
      
      	if((clientfd=socket(PF_INET,SOCK_STREAM,0))<0){  
      		perror("socket");  
      	}
      
      	if(connect(clientfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr))<0){
      		perror("connect");
      	}
      
      	int len;
      	FILE *fp;
      	char path[20];
      	gets(path);
      	fp=fopen(path, "r");
      	char readch;
      	int i=0;
      	while((readch=fgetc(fp))!=EOF){
      		if(i<1024){
      			buffer[i]=readch;
      			i++;
      		}
      		else{
      			i=0;
      			int n=send(clientfd, buffer, 1024, 0);
      		}
      	}
      	fclose(fp);
      	if(i!=0) send(clientfd, buffer, i, 0);
      	long wordscount;
      	recv(clientfd, &wordscount, sizeof(long), 0);
      	printf("%ld
      ", wordscount);
      	close(clientfd);
      }
      
    • 运行结果截图

    2 使用多线程实现wc服务器并使用同步互斥机制保证计数正确

    分析

    • 1中的客户端代码不需要改变,只需要改变服务器代码即可。
    • 服务器代码需要增加两个功能
      • 增加多线程
      • 使用同步互斥

    代码

    • 服务器
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <string.h>
    #include <pthread.h>
    
    #define MYPORT 155212
    pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
    
    char buffer[BUFSIZ];
    void *wc(void *m){
    	pthread_mutex_lock( &counter_mutex );
    	int len, i;
    	long wordscount=0;
    	int flag=1;
    	while(1){
    		if((len=recv(clientfd, buffer, 1024, 0))>0){
    			for(i=0; i<len; i++){
    				if(flag==0){
    					switch(buffer[i]){
    						case ' ':
    							wordscount++;
    							break;
    						case '
    ':
    							wordscount++;
    							break;
    						case '
    ':
    							wordscount++;
    							break;
    						default:
    							break;
    					}
    				}
    				if(buffer[i]== ' ' || buffer[i]=='
    ' || buffer[i]=='
    ') flag=1;
    				else flag=0;
    			}
    		}
    		if(len<1024) break;
    	}
    	send(clientfd, &wordscount, sizeof(long), 0);
    	close(clientfd);
    	pthread_mutex_unlock( &counter_mutex );
    	return NULL;
    }
    void main(){
    	pthread_t t;	
    	char arg[30];
    	int serverfd, clientfd;
    	struct sockaddr_in my_addr;
    	struct sockaddr_in remote_addr;
    
    	memset(&my_addr, 0, sizeof(my_addr));
    	my_addr.sin_family=AF_INET;
    	my_addr.sin_addr.s_add#include  <pthread.h>r=INADDR_ANY;
    	my_addr.sin_port=htons(MYPORT);
    
    	if((serverfd=socket(PF_INET, SOCK_STREAM, 0))==-1){
    		perror("socket");
    	}
    
    	if(bind(serverfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))<0){
    		perror("bind");
    	}
    	listen(serverfd, 5);
    	int addrlen=sizeof(struct sockaddr_in);	
    	while(1){
    		if((clientfd=accept(serverfd, (struct sockaddr *)&remote_addr, &addrlen))<0){
    			perror("accept");
    		}
    		printf("accept client %s
    ", inet_ntoa(remote_addr.sin_addr));
    		pthread_create(&t, NULL, &wc, NULL);
    		pthread_join(&t, NULL);
    	}
    	close(serverfd);
    }
    

    运行结果

    实验总结

    • 在本次实验中,实验进展比较慢,主要原因在于对socket编程不够熟悉,有一些错误一直没调出来,而且由于比较急,任务二的截图提交错了。在今后的实验中,需要更加提前准备实验,同时在提交截图时需要仔细确认。
    • 希望老师能多提前几天将其他实验的任务给我们,以便我们能充分准备好实验
  • 相关阅读:
    数组(Array)的使用方法
    Django中的事务操作
    什么是事务(Transaction)?事务的四个特性以及事务的隔离级别
    0.2 Django + Uwsgi + Nginx 的生产环境部署之实战篇
    0.1 Django + Uwsgi + Nginx 的生产环境部署之理论篇
    linux 进入编辑文件,保存退出相关命令
    Django--restframework
    使用用户名/邮箱/手机号 + 密码登陆 多形式登陆
    Django中异步任务---django-celery
    Redis 常用命令
  • 原文地址:https://www.cnblogs.com/dky20155212/p/7859380.html
Copyright © 2020-2023  润新知