• 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编程,线程,进程的关系优缺点。复习了操作系统课上的同步与互斥,用实例来更深刻的理解,还将刘念老师的实验也给做了。
  • 相关阅读:
    MS CRM 2011 RC中的新特性(4)——活动方面之批量编辑、自定义活动
    最近的一些有关MS CRM 2011的更新
    MS CRM 2011 RC中的新特性(6)——连接
    MS CRM 2011 RC中的新特性(7)—仪表板
    参加MS CRM2011深度培训课程——第一天
    MS CRM 2011插件调试工具
    MS CRM2011实体介绍(四)——目标管理方面的实体
    MS CRM 2011 RC中的新特性(3)——客户服务管理方面
    MS CRM 2011 RC中的新特性(8)—数据管理
    ExtAspNet 登陆
  • 原文地址:https://www.cnblogs.com/hpl20155329/p/7862348.html
Copyright © 2020-2023  润新知