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 5212

#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;  

}

在这里插入图片描述
3. 使用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上交叉编译
    在这里插入图片描述
posted on 2019-11-23 14:39  20175212thz  阅读(157)  评论(0编辑  收藏  举报