zoukankan      html  css  js  c++  java
  • 20155301信息安全系统设计基础第三次实验

    信息安全系统设计基础第三次实验

    实验一

    任务要求

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

    2)基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端

    3)客户端传一个文本文件给服务器

    4)服务器返加文本文件中的单词数

    实验步骤

    首先要在Linux中查看wc命令

    从中我们可以得知wc的命令是输出文章中的单词或者字符个数
    然后wc中有很多命令参数,它们各自的作用如下

    -c 统计字节数。

    -l 统计行数。

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

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

    -L 打印最长行的长度。

    -help 显示帮助信息

    --version 显示版本信息

    • 实现-c功能,利用stat函数实现

    • 实现-m功能,就是利用while(fgets(fp,buf,N)){i++}的方式实现

    • 实现-l功能,就是利用读文件,当读到' '的时候,就加1

    • 实现-w功能,也是读文件,但是在读到' ' ' '的时候加1

    运行代码

    客户端

    #include<stdio.h>
    #include<string.h>  
    #include<unistd.h>  
    #include<sys/stat.h>  
    #include<stdlib.h>
    #include<netinet/in.h>                         
    #include<sys/types.h>
    #include<sys/socket.h>                              
    #define HELLO_WORLD_SERVER_PORT       155339  
    #define BUFFER_SIZE                   1024  
    #define FILE_NAME_MAX_SIZE            512  
    int mywc(char file_name[],int choose);
    int main(int argc, char **argv)  
    {  
        FILE *fp;
        if (argc < 2)  
        {  
            printf("Usage: ./%s ServerIPAddress
    ", argv[0]);  
            exit(1);  
        }  
    
    // 设置一个socket地址结构client_addr, 代表客户机的internet地址和端口  
        struct sockaddr_in client_addr;  
        bzero(&client_addr, sizeof(client_addr));  
        client_addr.sin_family = AF_INET; // internet协议族  
        client_addr.sin_addr.s_addr = htons(INADDR_ANY); // INADDR_ANY表示自动获取本机地址  
        client_addr.sin_port = htons(0); // auto allocated, 让系统自动分配一个空闲端口  
    
    // 创建用于internet的流协议(TCP)类型socket,用client_socket代表客户端socket  
        int client_socket = socket(AF_INET, SOCK_STREAM, 0);  
        if (client_socket < 0)  
        {  
            printf("Create Socket Failed!
    ");  
            exit(1);  
        }  
    
    // 把客户端的socket和客户端的socket地址结构绑定   
        if (bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)))  
        {  
            printf("Client Bind Port Failed!
    ");  
            exit(1);  
        }  
    
    // 设置一个socket地址结构server_addr,代表服务器的internet地址和端口  
        struct sockaddr_in  server_addr;  
        bzero(&server_addr, sizeof(server_addr));  
        server_addr.sin_family = AF_INET;  
    
    // 服务器的IP地址来自程序的参数   
        if (inet_aton(argv[1], &server_addr.sin_addr) == 0)  
        {  
            printf("Server IP Address Error!
    ");  
            exit(1);  
        }                                                                                                               
        server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);  
        socklen_t server_addr_length = sizeof(server_addr);  
        // 向服务器发起连接请求,连接成功后client_socket代表客户端和服务器端的一个socket连接  
        if (connect(client_socket, (struct sockaddr*)&server_addr, server_addr_length) < 0)  
        {  
            printf("Can Not Connect To %s!
    ", argv[1]);  
            exit(1);  
        }  
    
          
        //bzero(argv[2], sizeof(argv[2]));    
        if((fp = fopen(argv[2],"r"))==NULL)
        {
             printf("Failure to open %s
    ",argv[2]);
             exit(0);
        }
        
        char buffer[BUFFER_SIZE];  
        bzero(buffer, sizeof(buffer));  
        char ch;
        int i=0;
        while((ch=fgetc(fp))!=EOF)
        {
            buffer[i++]=ch;
            if(i>=BUFFER_SIZE)
            {
                if((send(client_socket, buffer, BUFFER_SIZE, 0))==-1)
                {
                    printf("发送文件失败
    ");
                }
                bzero(buffer, sizeof(buffer));
                i=0;
            }
        }
        if(i<BUFFER_SIZE)
        {
            if((send(client_socket, buffer, i, 0))==-1)
            {
                printf("发送文件失败
    ");
            }
        }
        printf("发送%s完毕
    ",argv[2]);
        // 向服务器发送buffer中的数据,此时buffer中存放的是客户端需要接收的文件 
        //以下接收服务器发来的单词个数
        bzero(buffer, sizeof(buffer));
      int length ;  
      length = recv(client_socket, buffer, sizeof(buffer), 0);
      buffer[0]=atoi(buffer[0]);
      buffer[1]=atoi(buffer[1]);
      buffer[2]=atoi(buffer[2]);
          
            if (length < 0)  
            {  
                printf("Recieve Data From Server %s Failed!
    ", argv[1]);   
            }  
            else
            {
            printf("%d %d %d %S
    ",buffer[0],buffer[1],buffer[2],argv[2]);
    
            }
            bzero(buffer, BUFFER_SIZE);  
    // 传输完毕,关闭socket   
        
        fclose(fp);  
        close(client_socket);  
        return 0;  
    
    }  
    
    #### 服务器
    #include<netinet/in.h>   
    #include<sys/types.h>   
    #include<sys/socket.h>   
    #include<stdio.h>   
    #include<stdlib.h>   
    #include<string.h>     
    #include<unistd.h>  
    #include<sys/stat.h>  
    #include<stdlib.h>  
    #define HELLO_WORLD_SERVER_PORT    155339  
    #define LENGTH_OF_LISTEN_QUEUE     20  
    #define BUFFER_SIZE                1024  
    #define FILE_NAME_MAX_SIZE         512  
    struct message{  
            int lines;  
            int words;  
            int max_line_length;  
            int size;  
            int chars;  
    }info;  
    void error_print(char str[]){  
            printf("Error:%s",str);  
    }  
    void init(char filename[]){  
            struct stat get_message = {};  
            FILE *fp;  
            int ret_stat = stat(filename,&get_message);/*用stat函数读取filenmae文件的信息,并将结果写到get_message结构体中*/  
            if(ret_stat == -1){//stat函数不出错则进行信息输出  
                    error_print(filename);  
                    return ;  
            }  
            mode_t mode = get_message.st_mode;      //接收文件信息,用于下面判断是不是目录  
            int length = 0;  
            if(S_ISDIR(mode))   //如果是目录,输出错误  
                    printf("Error %s is dir
    0	0	0	%s",filename,filename);  
            else{  
                    info.size = get_message.st_size;    //文件字节大小 wc -c  
                    fp = fopen(filename,"r");   //以只读方式打开指定文件  
                    char ch;  
                    int flag = 0;  
                    while((ch = fgetc(fp))!=EOF){   //一直读到文件尾  
                            info.chars++;       //字符数加1 wc -m  
      
                            if(ch != '
    '){  
      
                                    length++;   //记录当前行的长度 wc -L  
                            }  
                            if(ch == '
    '){  
                                    info.lines ++;  //行数加1 wc -l  
                                    if(length>info.max_line_length)  
                                            info.max_line_length = length;  //更新最大长度  
                                    length = 0;  
                            }  
                            if(ch == '	' || ch == ' ' || ch == '
    '){  
                                    flag = 0;       //计算单词数 wc -w  
                                    continue;  
                            }  
                            else{  
      
                                    if(flag == 0){  
                                            info.words++;   //计算单词数 wc -w  
                                            flag = 1;  
                                    }  
                            }  
                    }  
                    fclose(fp);  
            }  
      
    }  
    
    int mywc(int argc,char *argv[]){  
      
            if(argc == 2){  
                    if(argv[1][0] != '-'){  
                            init(argv[1]);  
                            //printf("%d %d %d %s
    ",info.lines,info.words,info.size,argv[1]);  
                            return 0;  
                    } 
        }
            else if(argc == 3){  
                    init(argv[2]);  
            }  
            int num;  
            while((num = getopt(argc,argv,"lwmcL"))!=-1){  
                    switch(num){  
                            case 'l':  
                                    printf("%d
    ",info.lines);  
                                    break;  
                            case 'w':  
                                    printf("%d
    ",info.words);  
                                    break;  
                            case 'm':  
                                    printf("%d
    ",info.chars);  
                                    break;  
                            case 'c':  
                                    printf("%d
    ",info.size);  
                                    break;  
                            case 'L':  
                                    printf("%d
    ",info.max_line_length);  
                                    break;  
                    }  
            }  
            if(argc != 2 && argv[1][0] != '-')  //一定要判断,否则会越界  
                    printf("%s
    ",argv[2]);  
      
      
            return 0;  
    }
    int main(int argc, char **argv)  
    {  
    // set socket's address information   
    // 设置一个socket地址结构server_addr,代表服务器internet的地址和端口  
        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(HELLO_WORLD_SERVER_PORT);  
    // create a stream socket   
    // 创建用于internet的流协议(TCP)socket,用server_socket代表服务器向客户端提供服务的接口  
        int server_socket = socket(PF_INET, SOCK_STREAM, 0);  
        if (server_socket < 0)  
        {  
            printf("Create Socket Failed!
    ");  
            exit(1);  
        }  
    
    // 把socket和socket地址结构绑定   
        if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))  
        {  
            printf("Server Bind Port: %d Failed!
    ", HELLO_WORLD_SERVER_PORT);  
            exit(1);  
        }  
    
    // server_socket用于监听   
        if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))  
        {  
            printf("Server Listen Failed!
    ");  
            exit(1);  
        }  
    // 服务器端一直运行用以持续为客户端提供服务   
          
          
    // 定义客户端的socket地址结构client_addr,当收到来自客户端的请求后,调用accept  
    // 接受此请求,同时将client端的地址和端口等信息写入client_addr中  
            struct sockaddr_in client_addr;  
            int length = sizeof(client_addr);  
     
            int new_server_socket = accept(server_socket, (struct sockaddr*)&client_addr, &length);  
            printf("连接到客户端
    ");
            if (new_server_socket < 0)  
            {  
                printf("Server Accept Failed!
    ");  
                  
            }
            FILE *fp;
            if((fp = fopen("1.txt","w"))==NULL)
            {
                printf("Failure to open recvfile
    ");
                exit(0);
            }
    
            //接受来自客户端的文件
            char buffer[BUFFER_SIZE];  
            bzero(buffer, sizeof(buffer));  
            length=0;
            while( length = recv(new_server_socket, buffer, BUFFER_SIZE, 0) )
            {
                if(length<0)
                {
                    printf("接受文件出错
    ");
                    exit(0);
                }
                
                if(fwrite(buffer,sizeof(char),length,fp)<length)
                {
                    printf("写文件失败
    ");
                }
                bzero(buffer, BUFFER_SIZE);
            }
            fclose(fp);
            printf("成功接受文件
    ");
        char a[1]="1.txt";
            mywc(2,a);
            bzero(buffer, BUFFER_SIZE);  
            sprintf(buffer[0],%d,info.lines);
        sprintf(buffer[1],%d,info.words);
        sprintf(buffer[2],%d,info.size);
    // 发送buffer中的字符串到new_server_socket,实际上就是发送给客户端  
            if (send(new_server_socket, buffer, sizeof(buffer), 0) < 0)  
            {  
                printf("Send number Failed!
    ");  
                 
            } 
            printf("完成wc功能,并已返回给客户端
    ");
            bzero(buffer, sizeof(buffer));  
            
          fclose(fp);  
               
            close(new_server_socket);  
          
    
        close(server_socket);  
    
        return 0;  
    } 
    

    运行结果:

    客户端发给服务器一个文章,服务器调用mywc.c计算各种内容,然后把内容返回给客户端,即可实现实验一

    运行结果:

    实验二

    任务要求

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

    2.上方提交代码

    3.下方提交测试

    4.对比单线程版本的性能,并分析原因

    实现步骤

    实验二是关于多线程的,这需要在实验一的基础上利用pthread_create()函数把实验一改成多线程,首先用man命令查看多线程函数

    利用此函数将第一次的代码改写
    link

    运行代码

    #### 服务器
    #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出错,与该客户端连接的程序将退出
    "); 
                    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; 
    }
    

    客户端

    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; 
                    }
                }
                /*用户输入信息了,开始处理信息并发送*/
                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;
    }
    

    运行截图



  • 相关阅读:
    CodeForces 19D Points (线段树+set)
    FZU 2105 Digits Count
    HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
    HDU 5634 Rikka with Phi (线段树)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
  • 原文地址:https://www.cnblogs.com/fengxingck/p/7860211.html
Copyright © 2011-2022 走看看