码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-11-19 17:22:18      阅读:127      评论:0      收藏:0      [点我收藏+]

标签:return   define   描述符   实现   efi   success   sysstat   err   越界   

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

实验一

任务要求

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功能,就是利用读文件,当读到‘\n‘的时候,就加1
  • 实现-w功能,也是读文件,但是在读到‘\t‘ ‘\n‘的时候加1

    运行代码

    客户端

    include

    include

    include

    include<sys/stat.h>

    include

    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\n", 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!\n");
exit(1);
}

// 把客户端的socket和客户端的socket地址结构绑定
if (bind(client_socket, (struct sockaddr*)&client_addr, sizeof(client_addr)))
{
printf("Client Bind Port Failed!\n");
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!\n");
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!\n", argv[1]);
exit(1);
}

//bzero(argv[2], sizeof(argv[2]));    
if((fp = fopen(argv[2],"r"))==NULL)
{
     printf("Failure to open %s\n",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("发送文件失败\n");
        }
        bzero(buffer, sizeof(buffer));
        i=0;
    }
}
if(i<BUFFER_SIZE)
{
    if((send(client_socket, buffer, i, 0))==-1)
    {
        printf("发送文件失败\n");
    }
}
printf("发送%s完毕\n",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!\n", argv[1]);   
    }  
    else
    {
    printf("%d %d %d %S\n",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

include

include

include

include<sys/stat.h>

include

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\n0\t0\t0\t%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 != ‘\n‘){  

                            length++;   //记录当前行的长度 wc -L  
                    }  
                    if(ch == ‘\n‘){  
                            info.lines ++;  //行数加1 wc -l  
                            if(length>info.max_line_length)  
                                    info.max_line_length = length;  //更新最大长度  
                            length = 0;  
                    }  
                    if(ch == ‘\t‘ || ch == ‘ ‘ || ch == ‘\n‘){  
                            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\n",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\n",info.lines);  
                            break;  
                    case ‘w‘:  
                            printf("%d\n",info.words);  
                            break;  
                    case ‘m‘:  
                            printf("%d\n",info.chars);  
                            break;  
                    case ‘c‘:  
                            printf("%d\n",info.size);  
                            break;  
                    case ‘L‘:  
                            printf("%d\n",info.max_line_length);  
                            break;  
            }  
    }  
    if(argc != 2 && argv[1][0] != ‘-‘)  //一定要判断,否则会越界  
            printf("%s\n",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!\n");
exit(1);
}

// 把socket和socket地址结构绑定
if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)))
{
printf("Server Bind Port: %d Failed!\n", HELLO_WORLD_SERVER_PORT);
exit(1);
}

// server_socket用于监听
if (listen(server_socket, LENGTH_OF_LISTEN_QUEUE))
{
printf("Server Listen Failed!\n");
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("连接到客户端\n");
    if (new_server_socket < 0)  
    {  
        printf("Server Accept Failed!\n");  
          
    }
    FILE *fp;
    if((fp = fopen("1.txt","w"))==NULL)
    {
        printf("Failure to open recvfile\n");
        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("接受文件出错\n");
            exit(0);
        }
        
        if(fwrite(buffer,sizeof(char),length,fp)<length)
        {
            printf("写文件失败\n");
        }
        bzero(buffer, BUFFER_SIZE);
    }
    fclose(fp);
    printf("成功接受文件\n");
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!\n");

    } 
    printf("完成wc功能,并已返回给客户端\n");
    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

include

include

include

include <sys/socket.h>

include <arpa/inet.h>

include <netinet/in.h>

include <sys/types.h>

include

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!\n"); 
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!\n"); 
/*侦听本地端口*/ 
if(listen(sockfd,listnum) == -1){ 
    perror("listen"); 
    exit(errno); 
}else 
    printf("the server is listening!\n"); 
while(1){ 
    printf("*****************聊天开始***************\n"); 
    len = sizeof(struct sockaddr); 
    if((newfd = accept(sockfd,(struct sockaddr*) &c_addr, &len)) == -1){ 
        perror("accept"); 
        exit(errno); 
    }else 
        printf("正在与您聊天的客户端是:%s: %d\n",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出错,与该客户端连接的程序将退出\n"); 
            break; 
        }else if(retval == 0){ 
            printf("waiting...\n"); 
            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 请求终止聊天!\n"); 
                    break; 
                } 
                    len = send(newfd,buf,strlen(buf),0); 
                if(len > 0) 
                    printf("\t消息发送成功:%s\n",buf); 
                else{ 
                    printf("消息发送失败!\n"); 
                    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\n",buf); 
                else{ 
                    if(len < 0 ) 
                        printf("接受消息失败!\n"); 
                    else 
                        printf("客户端退出了,聊天终止!\n"); 
                    break; 
                } 
            } 
        } 
    } 
    /*关闭聊天的套接字*/ 
    close(newfd); 
    /*是否退出服务器*/ 
    printf("服务器是否退出程序:y->是;n->否? "); 
    bzero(buf, BUFLEN); 
    fgets(buf,BUFLEN, stdin); 
    if(!strncasecmp(buf,"y",1)){ 
        printf("server 退出!\n"); 
        break; 
    } 
} 
/*关闭服务器的套接字*/ 
close(sockfd); 
return 0; 

}

客户端

include

include

include

include

include <sys/socket.h>

include <arpa/inet.h>

include <netinet/in.h>

include <sys/types.h>

include

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!\n");


/*设置服务器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!\n");

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出错,客户端程序退出\n");
        break;
    }else if(retval == 0){
        printf("waiting...\n");
        continue;
    }else{
        /*服务器发来了消息*/
        if(FD_ISSET(sockfd,&rfds)){
            /******接收消息*******/
            bzero(buf,BUFLEN);
            len = recv(sockfd,buf,BUFLEN,0);
            if(len > 0)
                printf("服务器发来的消息是:%s\n",buf);
            else{
                if(len < 0 )
                    printf("接受消息失败!\n");
                else
                    printf("服务器退出了,聊天终止!\n");
            break; 
            }
        }
        /*用户输入信息了,开始处理信息并发送*/
        if(FD_ISSET(0, &rfds)){ 
            /******发送消息*******/ 
            bzero(buf,BUFLEN);
            fgets(buf,BUFLEN,stdin);
           
            if(!strncasecmp(buf,"quit",4)){
                printf("client 请求终止聊天!\n");
                break;
            }
                len = send(sockfd,buf,strlen(buf),0);
            if(len > 0)
                printf("\t消息发送成功:%s\n",buf); 
            else{
                printf("消息发送失败!\n");
                break; 
            } 
        }
    }

}
/*关闭连接*/
close(sockfd);

return 0;

}

运行截图

技术分享图片
技术分享图片
技术分享图片

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

标签:return   define   描述符   实现   efi   success   sysstat   err   越界   

原文地址:http://www.cnblogs.com/fengxingck/p/7860211.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!