zoukankan      html  css  js  c++  java
  • 2017-2018-1 20155329 实验三 实时系统

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

    实验目的

    第一题

    学习使用Linux命令wc(1)
    基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
    客户端传一个文本文件给服务器
    服务器返加文本文件中的单词数
    
    上方提交代码
    附件提交测试截图,至少要测试附件中的两个文件
    
    wc命令学习
    1. 命令格式:wc [选项]文件...
    2. 命令功能:统计指定文件中的字节数、字数、行数,并将统计结果显示输出。该命令统计指定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所指定文件的总统计数。
    3. 命令参数:

    -c 统计字节数。

    -l 统计行数。

    -m 统计字符数。这个标志不能与 -c 标志一起使用。

    -w 统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。

    -L 打印最长行的长度。

    -help 显示帮助信息

    -version 显示版本信息

    socket编程

    本段代码参考链接

    TCP_Service
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include <errno.h> 
    #include <sys/socket.h> 
    #include <arpa/inet.h> 
    #include <netinet/in.h> 
    #include <sys/types.h> 
    #include <unistd.h> 
    #include <sys/time.h> 
      
    #define BUFLEN 1024 
    #define PORT 6666
    #define LISTNUM 20
      
    int main() 
    { 
        int sockfd, newfd; 
        struct sockaddr_in s_addr, c_addr; 
        char buf[BUFLEN]; 
        socklen_t len; 
        unsigned int port, listnum; 
        fd_set rfds; 
        struct timeval tv; 
        int retval,maxfd; 
          
        /*建立socket*/ 
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){ 
            perror("socket"); 
            exit(errno); 
        }else 
            printf("socket create success!
    "); 
        memset(&s_addr,0,sizeof(s_addr)); 
        s_addr.sin_family = AF_INET; 
        s_addr.sin_port = htons(PORT); 
        s_addr.sin_addr.s_addr = htons(INADDR_ANY); 
        
        /*把地址和端口帮定到套接字上*/ 
        if((bind(sockfd, (struct sockaddr*) &s_addr,sizeof(struct sockaddr))) == -1){ 
            perror("bind"); 
            exit(errno); 
        }else 
            printf("bind success!
    "); 
        /*侦听本地端口*/ 
        if(listen(sockfd,listnum) == -1){ 
            perror("listen"); 
            exit(errno); 
        }else 
            printf("the server is listening!
    "); 
        while(1){ 
            printf("*****************聊天开始***************
    "); 
            len = sizeof(struct sockaddr); 
            if((newfd = accept(sockfd,(struct sockaddr*) &c_addr, &len)) == -1){ 
                perror("accept"); 
                exit(errno); 
            }else 
                printf("正在与您聊天的客户端是:%s: %d
    ",inet_ntoa(c_addr.sin_addr),ntohs(c_addr.sin_port)); 
            while(1){ 
                FD_ZERO(&rfds); 
                FD_SET(0, &rfds); 
                maxfd = 0; 
                FD_SET(newfd, &rfds); 
                /*找出文件描述符集合中最大的文件描述符*/ 
                if(maxfd < newfd) 
                    maxfd = newfd; 
                /*设置超时时间*/ 
                tv.tv_sec = 6; 
                tv.tv_usec = 0; 
                /*等待聊天*/ 
                retval = select(maxfd+1, &rfds, NULL, NULL, &tv); 
                if(retval == -1){ 
                    printf("select出错,
    :
    if(retval == -1){ 
                    printf("select出错,与该客户端连接的程序将退出
    "); 
                    break; 
                }else if(retval == 0){ 
                    printf("waiting...
    "); 
                    continue; 
                }else{ 
                    /*用户输入信息了*/ 
                    if(FD_ISSET(0, &rfds)){ 
                
                        /******发送消息*******/ 
                        memset(buf,0,sizeof(buf)); 
                        /*fgets函数:从流中读取BUFLEN-1个字符*/ 
                        fgets(buf,BUFLEN,stdin); 
                        /*打印发送的消息*/ 
                        //fputs(buf,stdout); 
                        if(!strncasecmp(buf,"quit",4)){ 
                            printf("server 请求终止聊天!
    "); 
                            break; 
                        } 
                            len = send(newfd,buf,strlen(buf),0); 
                        if(len > 0) 
                            printf("	消息发送成功:%s
    ",buf); 
                        else{ 
                            printf("消息发送失败!
    "); 
                            break; 
                        } 
                    } 
                    /*客户端发来了消息*/ 
                    if(FD_ISSET(newfd, &rfds)){ 
                        /******接收消息*******/ 
                        memset(buf,0,sizeof(buf)); 
                        /*fgets函数:从流中读取BUFLEN-1个字符*/ 
                        len = recv(newfd,buf,BUFLEN,0); 
                        if(len > 0) 
                            printf("客户端发来的信息是:%s
    ",buf); 
                        else{ 
                            if(len < 0 ) 
                                printf("接受消息失败!
    "); 
                            else 
                                printf("客户端退出了,聊天终止!
    "); 
                            break; 
                        } 
                    } 
                } 
            } 
            /*关闭聊天的套接字*/ 
            close(newfd); 
            /*是否退出服务器*/ 
            printf("服务器是否退出程序:y->是;n->否? "); 
            bzero(buf, BUFLEN); 
            fgets(buf,BUFLEN, stdin); 
            if(!strncasecmp(buf,"y",1)){ 
                printf("server 退出!
    "); 
                break; 
            } 
        } 
        /*关闭服务器的套接字*/ 
        close(sockfd); 
        return 0; 
    }
    
    TCP_Client
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <netinet/in.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <sys/time.h>
    
    #define BUFLEN 1024
    #define PORT 6666
    
    int main(int argc, char **argv)
    {
        int sockfd;
        struct sockaddr_in s_addr;
        socklen_t len;
        unsigned int port;
        char buf[BUFLEN];
        fd_set rfds;
        struct timeval tv;
        int retval, maxfd; 
        
        /*建立socket*/
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
            perror("socket");
            exit(errno);
        }else
            printf("socket create success!
    ");
    
        
        /*设置服务器ip*/
        memset(&s_addr,0,sizeof(s_addr));
        s_addr.sin_family = AF_INET;
         s_addr.sin_port = htons(PORT);
        if (inet_aton(argv[1], (struct in_addr *)&s_addr.sin_addr.s_addr) == 0) {
            perror(argv[1]);
            exit(errno);
        }
        /*开始连接服务器*/ 
        if(connect(sockfd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr)) == -1){
            perror("connect");
            exit(errno);
        }else
            printf("conncet success!
    ");
        
        while(1){
            FD_ZERO(&rfds);
            FD_SET(0, &rfds);
            maxfd = 0;
            FD_SET(sockfd, &rfds);
            if(maxfd < sockfd)
                maxfd = sockfd;
            tv.tv_sec = 6;
            tv.tv_usec = 0;
            retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
            if(retval == -1){
                printf("select出错,客户端程序退出
    ");
                break;
            }else if(retval == 0){
                printf("waiting...
    ");
                continue;
            }else{
                /*服务器发来了消息*/
                if(FD_ISSET(sockfd,&rfds)){
                    /******接收消息*******/
                    bzero(buf,BUFLEN);
                    len = recv(sockfd,buf,BUFLEN,0);
                    if(len > 0)
                        printf("服务器发来的消息是:%s
    ",buf);
                    else{
                        if(len < 0 )
                            printf("接受消息失败!
    ");
                        else
                            printf("服务器退出了,聊天终止!
    ");
                    break; 
                    }
    
    else
                            printf("服务器退出了,聊天终止!
    ");
                    break; 
                    }
                }
                /*用户输入信息了,开始处理信息并发送*/
                if(FD_ISSET(0, &rfds)){ 
                    /******发送消息*******/ 
                    bzero(buf,BUFLEN);
                    fgets(buf,BUFLEN,stdin);
                   
                    if(!strncasecmp(buf,"quit",4)){
                        printf("client 请求终止聊天!
    ");
                        break;
                    }
                        len = send(sockfd,buf,strlen(buf),0);
                    if(len > 0)
                        printf("	消息发送成功:%s
    ",buf); 
                    else{
                        printf("消息发送失败!
    ");
                        break; 
                    } 
                }
            }
        
        }
        /*关闭连接*/
        close(sockfd);
    
        return 0;
    }
    

    https://private.cdn.img.oss.mosoteach.cn/mssvc/attachment/2017/11/55208b6fc7744033c8b2c632a5766a43.JPG%40!s200x200?OSSAccessKeyId=95rMSbPQpR5gkRWs&Expires=2147483647&Signature=0WMzSjPPis%2FGZ55DjxbthalOVcw%3D

    第二题
    使用多线程实现wc服务器并使用同步互斥机制保证计数正确
    上方提交代码
    下方提交测试
    对比单线程版本的性能,并分析原因
    
    使用多线程

    linux 线程创建 同步与互斥 学习

    • 线程同步和互斥的区别:
    1. 互斥锁主要用来保护临界资源,什么是临界资源,就是有可能多个线程都需要访问的数据地址,也有可能是某一段代码,执行这段代码有可能会改变多个线程都需要访问的数据。

    2. 加入同步机制主要是为了在多线程程序中,如果需要对某个共享资源C进行同步访问,什么是同步访问,就是A线程访问过程中,B线程不能访问,必须等A线程访问结束后,B线程才能访问,而互斥锁,如果用来对C进行保护,A访问C资源的过程中,B不能访问,A访问结束后,B可以访问,但不一定访问的到,这取决于系统的调度是否给到B,如果没有,A反而被调度到了,那么A就有可能方法到C。

    3. 反观同步机制,在这种情况下,如果系统没有调度到B,A也是没有可能访问C的,必须等B调度到之后,A才可能重新访问。

    单线程
    • 单线程程序:只有一个线程,代码顺序执行,容易出现代码阻塞(页面假死)
    多线程
    • 使用多线程编程的目的:就是"最大限度地利用CPU资源"
    • 坏处:增加了调度和管理的开销,带来了一些不确定性,需要复杂的同步机制,避免死锁等等。
    • 好处:一定程度上提高响应速度,在多核的情况下还是更能充分利用CPU资源的。
    • 线程相对于进程的缺点:
    1. 共享资源需要耗费一定的锁资源,同步相对复杂。
    2. 一个线程崩溃可能导致整个进程崩溃,这个当然是自己的应用程序有问题
      {{uploading-image-990117.png(uploading...)}}

    感想

    • 本次实验将操作系统,web编程中的socket编程都覆盖到了,第二题还将线程加入进来,在做实验的过程中查看了很多相关博客,参考了挺多代码,在参考代码的同是看到了很多大神们的简介,阐述了socket编程,线程,进程的关系优缺点。复习了操作系统课上的同步与互斥,用实例来更深刻的理解,还将刘念老师的实验也给做了。
  • 相关阅读:
    进行C# 编写发送邮箱,报错Error: need EHLO and AUTH first !
    vue使jsZip和FileSaver.js打包下载
    基于js或vue项目实现一次批量文件下载功能
    模块
    now 与 down 中的 ow 发音是否一样?
    __time64_t 解决了 2038 年问题,可是没解决 1969年问题
    MagickSetOption(mw, "jpeg:extent", "...kb"); 这个函数有时结果出乎意料
    解决Idea启动Spring Boot很慢的问题
    CAP原理和BASE思想和ACID模型
    java并发编程之Condition
  • 原文地址:https://www.cnblogs.com/hpl20155329/p/7862348.html
Copyright © 2011-2022 走看看