2019-2020-1 20175212童皓桢《信息安全系统设计》 实验三并发程序

2019-2020-1 20175212童皓桢《信息安全系统设计》 实验三并发程序

并发程序-1

实验要求

  • 学习使用Linux命令wc(1)
  • 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
  • 客户端传一个文本文件给服务器
  • 服务器返加文本文件中的单词数

实验步骤

  1. 使用man wc学习wc命令的功能用法
    在这里插入图片描述
  2. 用socket编程实现
client.c

#include<netinet/in.h>   // sockaddr_in  

#include<sys/types.h>    // socket  

#include<sys/socket.h>   // socket  

#include<stdio.h>        // printf  

#include<stdlib.h>       // exit  

#include<string.h>       // bzero  

#include <arpa/inet.h>

#include <unistd.h>

#include "head.h"



#define SERVER_PORT 5212

#define BUFFER_SIZE 1024  

#define FILE_NAME_MAX_SIZE 512  

#define BEGIN 1;



int main()  

{

    struct sockaddr_in client_addr;  

    bzero(&client_addr, sizeof(client_addr));  

    client_addr.sin_family = AF_INET;  

    client_addr.sin_addr.s_addr = htons(INADDR_ANY);  

    client_addr.sin_port = htons(0);  

    int client_socket_fd = socket(AF_INET, SOCK_STREAM, 0);  

    if(client_socket_fd < 0)  

    {  

            perror("Create Socket Failed!");  

            exit(1);  

    }  

    if(-1 == (bind(client_socket_fd, (struct sockaddr*)&client_addr, sizeof(client_addr))))  

    {  

            perror("Client Bind Failed!");  

            exit(1);  

    }

    struct sockaddr_in server_addr;  

    bzero(&server_addr, sizeof(server_addr));  

    server_addr.sin_family = AF_INET;  

    if(inet_pton(AF_INET, "127.0.0.1", &server_addr.sin_addr) == 0)  

    {  

            perror("Server IP Address Error!");  

            exit(1);  

    }  

    server_addr.sin_port = htons(SERVER_PORT);  

    socklen_t server_addr_length = sizeof(server_addr);  

    if(connect(client_socket_fd, (struct sockaddr*)&server_addr, server_addr_length) < 0)  

    {  

            perror("Can Not Connect To Server IP!");  

            exit(0);  

    }  

    char file_name[FILE_NAME_MAX_SIZE+1];  

    bzero(file_name, FILE_NAME_MAX_SIZE+1);  

    printf("Please Input File Name On Client: ");

    scanf("%s", file_name);  

    char buffer[BUFFER_SIZE];  

    bzero(buffer, BUFFER_SIZE);  

    strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name));  

    if(send(client_socket_fd, buffer, BUFFER_SIZE, 0) < 0)  

    {  

            perror("Send File Name Failed!");  

            exit(1);  

    }

        FILE *fp = fopen(file_name, "r");  

        if(NULL == fp)  

        {  

            printf("File: %s Not Found!\n", file_name);  

        }  

        else  

        {  

            bzero(buffer, BUFFER_SIZE);  

            int length = 0;  

            while((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)

            {

                    if(send(client_socket_fd, buffer, length, 0) < 0)  

                    {  

                        printf("Send File: %s Failed!/n", file_name);  

                        break;  

                    }  

                    bzero(buffer, BUFFER_SIZE);  

            }  

        printf("Send File: %s Successful!\n", file_name);

        printf("The File has %d words.\n",wcfunc(file_name));     

        }  

/*

    char s[50];

    scanf("%s",s);

    send(client_socket_fd,"OK",50,0);



    char recvdata[sizeof(int)+1];

    recv(client_socket_fd,recvdata,sizeof(int),0);

    recvdata[sizeof(int)]='\0';

    int words=atoi(recvdata);*/

    fclose(fp);

    close(client_socket_fd);  

    return 0;  

}



int wcfunc(char *file_name)

{

    int t;

    int w = 0;

    int state = 0;

    FILE *in;

    if((in = fopen(file_name,"r"))==NULL)

    {

        printf("wc %s:no this file or dir\n",file_name);

        return 0;

    }

    while((t=fgetc(in))!=EOF)

    {

        

        if(t=='\n'||t==' '||t=='\r') {

                    state = 0;

                    continue;

            } else {

                    if(state == 0) {

                    state = 1;

                    w++;

                }

                    continue;

            }

    }

    return w;

}
server.c

#include<netinet/in.h>  // sockaddr_in  

#include<sys/types.h>   // socket  

#include<sys/socket.h>  // socket  

#include<stdio.h>       // printf  

#include<stdlib.h>      // exit  

#include<string.h>      // bzero  

#include <unistd.h>



#define SERVER_PORT 5223

#define LENGTH_OF_LISTEN_QUEUE 20  

#define BUFFER_SIZE 1024

#define FILE_NAME_MAX_SIZE 512  

#define BEGIN 1; 



int main(void)  

{  



    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(SERVER_PORT);  



    int server_socket_fd = socket(PF_INET, SOCK_STREAM, 0);  

    if(server_socket_fd < 0)  

    {  

        perror("Create Socket Failed!");  

            exit(1);  

    }  

    int opt = 1;  

    setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));  



    if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))  

    {  

            perror("Server Bind Failed!");  

            exit(1);  

    }  

        

    if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))  

    {  

            perror("Server Listen Failed!");  

            exit(1);  

    }  



    while(1)  

    {  

            struct sockaddr_in client_addr;  

            socklen_t client_addr_length = sizeof(client_addr);  



            int new_server_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr, &client_addr_length);  

            if(new_server_socket_fd < 0)  

            {  

            perror("Server Accept Failed!");  

            break;  

            }  





        char buffer[BUFFER_SIZE];  

        bzero(buffer, BUFFER_SIZE);  

        if(recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0) < 0)  

        {  

            perror("Server Recieve Data Failed!");  

            break;  

        }  





            char file_name[FILE_NAME_MAX_SIZE+1];  

            bzero(file_name, FILE_NAME_MAX_SIZE+1);  

            strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));  

        printf("%s\n", file_name);  



            FILE *fp = fopen(file_name, "w");  

            if(NULL == fp)  

            {  

            printf("File: %s Can Not Open To Write\n", file_name);  

            exit(1);  

            }  





            bzero(buffer, BUFFER_SIZE);  

            int length = 0;  

            while((length = recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0)) > 0)  

            {  

                if(strcmp(buffer,"OK")==0) 

                break;

            if(fwrite(buffer, sizeof(char), length, fp) < length)  

            {  

                    printf("File: %s Write Failed!\n", file_name);  

                    break;  

            }  

            bzero(buffer, BUFFER_SIZE);  

        }  



            printf("Receive File: %s From Client Successful!\n", file_name);  

            fclose(fp);



        int words=0;

        char s[100];

        FILE *fp2;

        if((fp2=fopen(file_name,"r"))==NULL)

        {

                printf("ERROR!\n");

                exit(0);

        }

        while(fscanf(fp2,"%s",s)!=EOF)

            words++;

        fclose(fp2);

        printf("%d words.\n",words);



        char sendbuf[50];

        sprintf(sendbuf,"%d",words);

        send(new_server_socket_fd,sendbuf,50,0);

            close(new_server_socket_fd);  

    }

    close(server_socket_fd);  

    return 0;  

}

在这里插入图片描述

  1. 使用wc功能检查
    在这里插入图片描述

    并发程序-2

    实验要求

  • 使用多线程实现wc服务器并使用同步互斥机制保证计数正确
  • 对比单线程版本的性能,并分析原因

实验步骤

  1. 使用socket编程
clinet.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <fcntl.h>

#include <unistd.h>

#include <pthread.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#include "head.h"

#define BUFFER_SIZE 1024  

#define FILE_NAME_MAX_SIZE 512 



static void usage(const char* proc)

{

    printf("%s[server_ip][server_port]\n", proc);

}



//./client server_ip, server_port

int main(int argc, char* argv[])

{

    if(argc != 3)

    {

        usage(argv[0]);

        return 1;

    }

    //1.创建sock

    int sock = socket(AF_INET, SOCK_STREAM, 0);

    if(sock < 0)

    {

        perror("socket");

        return 2;

    }

    //2.connect

    struct sockaddr_in server;

    server.sin_family = AF_INET;

    server.sin_port = htons(atoi(argv[2]));

    //将点分十进制的字符串转换成能在网络上传输的网络号

    server.sin_addr.s_addr = inet_addr(argv[1]);

    //调用connect,第一个参数是客户端的socket套接字,第二个参数是服务器端套接字

    if(connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0)

    {

        perror("connect");

        return 2;

    }

    /*//先写后读

    char buf[1024];

    while(1)

    {

        printf("Please enter# ");

        fflush(stdout);

        //读取标准输入键盘中的数据

        ssize_t s = read(0, buf, sizeof(buf) - 1);

        if(s > 0)

        {

            buf[s - 1] = 0;

            //将buf中的内容写到套接字中

            write(sock, buf, strlen(buf));

            //读取服务器的响应

            ssize_t _s = read(sock, buf, sizeof(buf)-1);

            if(_s > 0)

            {

                buf[_s] = 0;

                printf("server ech0# %s\n", buf);

            }

        }

    }*/

    char file_name[FILE_NAME_MAX_SIZE+1];  

    bzero(file_name, FILE_NAME_MAX_SIZE+1);  

    printf("Please Input File Name On Client: ");

    scanf("%s", file_name);  

    char buffer[BUFFER_SIZE];  

    bzero(buffer, BUFFER_SIZE);  

    strncpy(buffer, file_name, strlen(file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(file_name));  

    if(send(sock, buffer, BUFFER_SIZE, 0) < 0)  

    {

    perror("Send File Name Failed!");

    exit(1);  

    }

    FILE *fp = fopen(file_name, "r");  

    if(NULL == fp)  

    {  

        printf("File: %s Not Found!\n", file_name);  

    }  

    else  

    {  

        bzero(buffer, BUFFER_SIZE);  

        int length = 0;  

        while((length = fread(buffer, sizeof(char), BUFFER_SIZE, fp)) > 0)

        {

            if(send(sock, buffer, length, 0) < 0)  

            {  

                printf("Send File: %s Failed!/n", file_name);  

                break;  

            }  

            bzero(buffer, BUFFER_SIZE);  

        }  

    printf("Send File: %s Successful!\n", file_name);

    printf("The File has %d words.\n",wcfunc(file_name));     

    }

    fclose(fp);

    close(sock);

    return 0;

}



int wcfunc(char *file_name)

{

    int t;

    int w = 0;

    int state = 0;

    FILE *in;

    if((in = fopen(file_name,"r"))==NULL)

    {

        printf("wc %s:no this file or dir\n",file_name);

        return 0;

    }

    while((t=fgetc(in))!=EOF)

    {

        

        if(t=='\n'||t==' '||t=='\r') {

                    state = 0;

                    continue;

            } else {

                    if(state == 0) {

                    state = 1;

                    w++;

                }

                    continue;

            }

    }

    return w;

}
server.c

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <fcntl.h>

#include <pthread.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#define BUFFER_SIZE 1024

#define FILE_NAME_MAX_SIZE 512

static void Usage(char* proc)

{

    printf("%s[local_ip], [local_port]\n", proc);

}

int startup(char* _ip, int _port)

{

    int sock = socket(AF_INET, SOCK_STREAM, 0);

    if(sock < 0)

    {

        perror("socket");

        return 1;

    }

    struct sockaddr_in local;//初始化协议地址

    local.sin_family = AF_INET;

    local.sin_port = htons(_port);

    local.sin_addr.s_addr = inet_addr(_ip);

    //将套接字和tcp服务绑定(服务端ip地址)

    if(bind(sock, (struct sockaddr*)&local, sizeof(local)) < 0)

    {

        perror("bind");

        exit(3);

    }

    //监听这个套接字,监听指定端口,第二个参数表示可以排队连接的最大个数

    if(listen(sock, 5) < 0)

    {

        perror("listen");

    }

    return sock;

}

void* handle(void* argc)

{

    int newsock = (int)argc;

    char buf[1024];

    while(1)

    {

        int s = read(newsock, buf, sizeof(buf) - 1);

        if(s > 0)

        {

            buf[s] = 0;

            printf("client# %s\n", buf);

            write(newsock, buf, strlen(buf));//服务器回显

        }

        else if(s == 0)

        {

            printf("client quit\n");

        }

        else

        {

            break;

        }

    }

    close(newsock);

}

//argv[]指针数组,指向各个参数

int main(int argc, char* argv[])

{

    if(argc != 3)

    {

        Usage(argv[0]);

        return 2;

    }

    int listen_sock = startup(argv[1], atoi(argv[2]));

    //printf("sock:%d\n", listen_sock);

    //需要让子进程的子进程去提供服务

    //父进程继续监听

    char buf[1024];

    while(1)

    {

        struct sockaddr_in client;

        socklen_t len = sizeof(client);

        int newsock = accept(listen_sock, (struct sockaddr*)&client, &len);

        if(newsock < 0)

        {

            perror("accept");

            continue;

        }

        //将网络中的数据转换为主机用户可以看懂的数据

        printf("get a new client %s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));

        //创建一个新的线程去服务

        //主线程只负责监听工作

        pthread_t tid;

        //pthread_create(&tid, NULL, handle, (void*)newsock);

        pthread_detach(tid);



    /*char buffer[BUFFER_SIZE]; 

    bzero(buffer, BUFFER_SIZE); 

    char file_name[FILE_NAME_MAX_SIZE+1];  

    bzero(file_name, FILE_NAME_MAX_SIZE+1);  

        strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));  

    printf("%s\n", file_name);  

        FILE *fp = fopen(file_name, "w");  

        if(NULL == fp)  

        {  

        printf("File: %s Can Not Open To Write\n", file_name);  

        exit(1);  

        }  

    bzero(buffer, BUFFER_SIZE);  

        int length = 0;  

        while((length = recv(newsock, buffer, BUFFER_SIZE, 0)) > 0)  

        {  

        if(strcmp(buffer,"OK")==0) 

        break;

        if(fwrite(buffer, sizeof(char), length, fp) < length)  

        {  

        printf("File: %s Write Failed!\n", file_name);  

            break;  

        }  

            bzero(buffer, BUFFER_SIZE);  

    }  

        printf("Receive File: %s From Client Successful!\n", file_name);  

        fclose(fp);



    int words=0;

    char s[100];

    FILE *fp2;

    if((fp2=fopen(file_name,"r"))==NULL)

    {

        printf("ERROR!\n");

        exit(0);

    }

    while(fscanf(fp2,"%s",s)!=EOF)

    words++;

    fclose(fp2);

    printf("%d words.\n",words);

    char sendbuf[50];

    sprintf(sendbuf,"%d",words);

    send(newsock,sendbuf,50,0);

        close(newsock);*/

    }

    close(listen_sock);

    return 0;

}

在这里插入图片描述
分析原因:相较于单线程而言,多线程的各种进程可以同时执行,而不需要像单线程一样排队执行,不易出现进程阻塞,性能更好

  1. 用wc命令检查
    [在这里插入图片描述](https://img-blog.csdnimg.cn/20191123141702980.JPG?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDgyNjMzOA==,size_16,color_FFFFFF,t_70

并发程序-3

实验要求

  • 交叉编译多线程版本服务器并部署到实验箱中

  • PC机作客户端测试wc服务器

  • 提交测试截图

实验步骤

1.参照实验一,将PC连接到试验箱,并使其能互相ping通。
在这里插入图片描述

  1. 在ubuntu上交叉编译
    在这里插入图片描述

猜你喜欢

转载自www.cnblogs.com/thz666/p/11917931.html