• 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;
    }
    

    运行截图



  • 相关阅读:
    Google Map API基本概念(转载)很好的例子
    Sql Exception Handling & Throw Exception
    幸福人生讲座(十):五伦中哪一伦最重要?
    Delete Database Log
    杨澜语录
    余世雄 如何提升职场“执行力”
    红楼女梦
    假如我真的看透了
    余世维 有效沟通
    习惯修养
  • 原文地址:https://www.cnblogs.com/fengxingck/p/7860211.html
Copyright © 2020-2023  润新知