zoukankan      html  css  js  c++  java
  • 2018-2019-1 实验三 并发程序

    实验三 并发程序

    任务一

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

    server:

    include <netinet/in.h>

    include <sys/types.h>

    include <sys/socket.h>

    include <stdio.h>

    include <stdlib.h>

    include <string.h>

    include <unistd.h>

    define HELLO_WORLD_SERVER_PORT 5213

    define LENGTH_OF_LISTEN_QUEUE 20

    define BUFFER_SIZE 1024

    define FILE_NAME_MAX_SIZE 512

    define FILE_WORDS_NUMBER 32

    int wc_func(char *file_name);
    int main(int argc, char **argv)
    {
    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);

    					    int server_socket = socket(PF_INET,SOCK_STREAM,0);
    						    if( server_socket < 0)
    								    {
    										        printf("Create Socket Failed!");
    												        exit(1);
    														    }
    							    
    							    if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))
    									    {
    											        printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT); 
    													        exit(1);
    															    }
    								    
    
    								    if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) )
    										    {
    												        printf("Server Listen Failed!"); 
    														        exit(1);
    																    }
    									    while (1) 
    											    {
    
    													        struct sockaddr_in client_addr;
    															        socklen_t length = sizeof(client_addr);
    
    
    																	        int new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
    																			        if ( new_server_socket < 0)
    																						        {
    																									            printf("Server Accept Failed!
    ");
    																												            break;
    																															        }
    																					        
    																					    char file_name[FILE_NAME_MAX_SIZE+1];
    																						    bzero(file_name, FILE_NAME_MAX_SIZE+1);
    																							    char buffer[BUFFER_SIZE];
    																								    bzero(buffer,BUFFER_SIZE);
    																									    recv(new_server_socket,file_name,BUFFER_SIZE,0);
    																										    
    																										    
    																										    FILE * fp = fopen(file_name,"w");
    																											    if(NULL == fp )
    																													    {
    																															        printf("File:	%s Can Not Open To Write
    ", file_name);
    																																	        exit(1);
    																																			    }
    																												    
    																												   
    																												    bzero(buffer,BUFFER_SIZE);
    																													    int len = 0;
    																														    while( len = recv(new_server_socket,buffer,BUFFER_SIZE,0))
    																																    {
    																																		        if(len < 0)
    																																					        {
    																																								            printf("Recieve Data From Client %s Failed!
    ", argv[1]);
    																																											            break;
    																																														        }
    
    																																				        int write_length = fwrite(buffer,sizeof(char),len,fp);
    																																						        if (write_length<len)
    																																									        {
    																																												            printf("File:	%s Write Failed
    ", file_name);
    																																															            break;
    																																																		        }
    																																								        bzero(buffer,BUFFER_SIZE);    
    																																										    }
    																															    printf("File:	%s Transfer Finished!
    ",file_name);
    																																    
    																																    fclose(fp);
    																																	   
    																																	    close(new_server_socket);
    																																		    }
    										    close(server_socket);
    											    return 0;
    

    }

    client:

    include <netinet/in.h>

    include <sys/types.h>

    include <sys/socket.h>

    include <stdio.h>

    include <stdlib.h>

    include <string.h>

    include <unistd.h>

    define HELLO_WORLD_SERVER_PORT 5213

    define BUFFER_SIZE 1024

    define FILE_NAME_MAX_SIZE 512

    define FILE_WORDS_NUMBER 32

    int main(int argc, char **argv)
    {
    if (argc != 2)
    {
    printf("Usage: ./%s ServerIPAddress ",argv[0]);
    exit(1);
    }
    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);//INADDR_ANY表示自动获取本机地址
    client_addr.sin_port = htons(0);
    int client_socket = socket(AF_INET,SOCK_STREAM,0);
    if( client_socket < 0)
    {
    printf("Create Socket Failed! ");
    exit(1);
    }
    if( bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr)))
    {
    printf("Client Bind Port Failed! ");
    exit(1);
    }
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    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);

    															    if(connect(client_socket,(struct sockaddr*)&server_addr, server_addr_length) < 0)
    																	    {
    																			        printf("Can Not Connect To %s!
    ",argv[1]);
    																					        exit(1);
    																							    }
    
    																    char file_name[FILE_NAME_MAX_SIZE+1];
    																	    bzero(file_name, FILE_NAME_MAX_SIZE+1);
    																		    printf("Please Input File Name On Server:	");
    																			    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));
    																							    send(client_socket,buffer,BUFFER_SIZE,0);
    
    																								    FILE * fp = fopen(file_name,"r");
    																									    if(NULL == fp )
    																											    {
    																													        printf("File:	%s Not Found
    ", file_name);
    																															        exit(1);
    																																	    }
    																										    else
    																												    {
    																														            bzero(buffer, BUFFER_SIZE);
    																																	            int file_block_length = 0;
    																																				            while( (file_block_length = fread(buffer,sizeof(char),BUFFER_SIZE, fp))>0)
    																																								            {
    																																												                if(send(client_socket,buffer,file_block_length,0)<0)
    																																																	                {
    																																																						                    printf("Send File:	%s Failed
    ", file_name);
    																																																											                    break;
    																																																																                }
    																																																                bzero(buffer, BUFFER_SIZE);
    																																																				            }
    																																							    }
    																											    
    																											    printf("Send File:	 %s To Server[%s] Finished
    ",file_name, argv[1]);
    																													
    																												    printf("The File has %d words.
    ", wc_func(file_name));
    																													    fclose(fp);
    																														  
    
    																														    close(client_socket);
    																															    return 0;
    

    }
    int wc_func(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 ",file_name);
    return;
    }
    while((t=fgetc(in))!=EOF)
    {

    											if(t=='
    '||t==' '||t=='
    ') {
    												            		state = 0;
    																	            		continue;
    																						        	} else {
    																										            		if(state == 0) {
    																																                	state = 1;
    																																					                	w++;
    																																										           		}
    																															            		continue;
    																																				        	}
    





    任务二

    使用多线程实现wc服务器并使用同步互斥机制保证计数正确
    上方提交代码
    下方提交测试
    对比单线程版本的性能,并分析原因

    原因:所有数据结构的生存期,以及对这些数据结构的access,都用这一根逻辑线程。
    不需要考虑数据结构的race。
    把任何耗时的操作都给其他线程(IO线程、定时器线程,DB线程等)做,做完之后向事件队列(多线程安全的队列,其他线程是生产者,逻辑线程是消费者)丢事件。
    多线程逻辑设计的思路:
    所有数据结构的生存期,以及对这些数据结构的access,不一定在一根线程。
    需要考虑数据结构的race。
    网络事件、定时器事件唤醒工作线程(一般通过iocp或者epoll来唤醒)执行所有工作,一般不需要交换到其他线程。
    很显然,单线程逻辑多了一层事件队列交换,会增加延迟,以及所有的逻辑都在一根线程上跑,逻辑被阻塞也会带来延迟。
    其实吞吐量对于rpc来说,是个宏观的概念,尽可能快地消费网络消息就会提升吞吐量。
    对于高并发的程序,是无法忍受单线程逻辑

    server:

    include <stdio.h>

    include <fcntl.h>

    include <pthread.h>

    include <sys/stat.h>

    include <sys/types.h>

    include <sys/socket.h>

    include <arpa/inet.h>

    define PORT 8887

    define BUFF_SIZE 1024

    define LISTEN_SIZE 20

    typedef struct{
    char type;
    char data[BUFF_SIZE];
    }m_package;

    void* process_client();

    int main(){
    int ss = create_tcp_server(PORT);
    if(-1 == ss)
    exit(-1);
    while(1){
    //接受客户端连接
    socklen_t addrlen = sizeof(struct sockaddr);
    struct sockaddr_in client_addr; //客户端地址结构
    int client_sock = accept(ss, (struct sockaddr*)&client_addr, &addrlen);
    if(client_sock < 0){
    printf("accept error ");
    }
    printf("accept success ");

        pthread_t pid;
        if(pthread_create(&pid, NULL, process_client, &client_sock) < 0){
            printf("pthread_create error
    ");
        }
    }
    

    }

    //处理客户端程序
    void *process_client(void *arg){
    int size = 0, fd, count = 0, sockid = (int)arg;
    m_package pac;
    long total = 0, cur = 0;
    //循环接收文件
    while(1) {
    memset(&pac, 0, sizeof(pac));
    size = read(sockid, &pac, sizeof(pac));
    if(size > 0){
    if (pac.type == 1){
    fd = open(pac.data, O_CREAT|O_WRONLY, 0777);
    if(-1 == fd){
    printf("open file error! ");
    continue;
    }
    count = total = cur = 0;
    }
    else if (pac.type == 2){
    cur += write(fd, pac.data, strlen(pac.data));
    if(count++ % 5000 == 0){
    printf("recv from client < %d > : %.01lf% ", sockid, cur * 100.0 / total);
    count = 0;
    }
    }
    else if (pac.type == 3){
    printf("recv from client < %d > : 100.0% ", sockid);
    printf("recv success ");
    close(fd);
    }
    else if(pac.type == 4){//文件长度
    total = strtol(pac.data, NULL, 10);
    printf("%ld ", total);
    }
    }else{
    printf("client disconnected ");
    close(sockid);
    break;
    }
    }
    return 0;
    }
    int start_server(int port, int type){
    //建立服务器套接字
    int ss = socket(AF_INET, type, 0);
    if(ss < 0){
    printf("create socket error ");
    return -1;
    }

    //设置服务器地址
    struct sockaddr_in server_addr;	//服务器地址结构
    bzero(&server_addr, sizeof(struct sockaddr_in)); //清零
    server_addr.sin_family = AF_INET; //协议族
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //ip地址
    server_addr.sin_port = htons(port); //端口
    //绑定地址结构到套接字描述符
    if(bind(ss, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0){
        printf("bind error
    ");
        return -1;
    }
    //TCP
    if(SOCK_STREAM == type){
        //设置侦听
        if(listen(ss, LISTEN_SIZE) < 0){
            printf("listen error
    ");
            return -1;
        }
        printf("tcp server start
    ");
    }
    else
        printf("udp server start
    ");
    return ss;
    

    }

    int create_tcp_server(int port){
    start_server(port, SOCK_STREAM);
    }

    int create_udp_server(int port){
    start_server(port, SOCK_DGRAM);
    }

    client:#include <stdio.h>

    include <fcntl.h>

    include <pthread.h>

    include <sys/stat.h>

    include <sys/types.h>

    include <sys/socket.h>

    include <arpa/inet.h>

    define PORT 8887

    define BUFF_SIZE 1024

    define LISTEN_SIZE 20

    typedef struct{
    char type;
    char data[BUFF_SIZE];
    }m_package;

    int main(){
    //创建连接
    int sock_fd = connect_tcp("127.0.0.1", PORT);
    if(-1 == sock_fd)
    return -1;

    m_package pac;
    int fd, cur = 0, count = 0;
    long filesize = 0;
    while(1){
        //打开文件
        memset(&pac, 0, sizeof(pac));
        pac.type = 1;
        // strcpy(pac.data, "/home/SKZH/a.txt");
        scanf("%s", pac.data);
        //获取文件信息
        struct stat sfile;
        stat(pac.data, &sfile );
        filesize = sfile.st_size;
        time_t t;
        long begin = time(&t);
        cur = count = 0;
    
        fd = open(pac.data, O_RDONLY);
        if(-1 == fd){
            printf("file open error
    ");
            continue;
        }
        //读取文件并发送
        //发送文件名
        strcpy(pac.data, strrchr(pac.data, '/') + 1);
        write(sock_fd, &pac, sizeof(pac));
        memset(&pac, 0, sizeof(pac));
    
        //发送文件长度
        pac.type = 4;
        sprintf(pac.data,"%ld",filesize);
        write(sock_fd, &pac, sizeof(pac));
        memset(&pac, 0, sizeof(pac));
    
        int read_len = 0;
        while((read_len = read(fd, pac.data, BUFF_SIZE)) > 0){
            pac.type = 2;
            write(sock_fd, &pac, sizeof(pac));
            memset(&pac, 0, sizeof(pac));
            cur += read_len;
            if(count++ % 5000 == 0){
                count = 0;
                printf("send to server : %.1lf\%
    ", cur * 100.0 / filesize);
            }
        }
    
        //发送结束标记
        memset(&pac, 3, sizeof(pac));
        write(sock_fd, &pac, BUFF_SIZE + 1);
        close(fd);
    
        printf("send to server : 100.0\%
    ");
        printf("file size : %d B
    ", filesize);
        printf("time : %ld ms
    ", time(&t) - begin);
        printf("send file success
    ");
        printf("------------------------
    ");
    }
    close(sock_fd);
    

    }
    int connectsock(char* server_ip, int server_port, int type){
    int sock_fd = socket(AF_INET, type, 0);
    if(-1 == sock_fd){
    printf("create socket error ");
    return -1;
    }

    struct sockaddr_in server_addr;
    //设置服务器地址
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    server_addr.sin_port = htons(server_port);
    inet_pton(AF_INET, server_ip, &server_addr.sin_addr);
    
    //连接服务器
    if(-1 == connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(struct sockaddr_in))){
        printf("connect server error
    ");
        return -1;
    }
    
    printf("connect server success
    ");
    return sock_fd;
    

    }

    int connect_tcp(char* server_ip, int server_port){
    return connectsock(server_ip, server_port, SOCK_STREAM);
    }

    int connect_udp(char* server_ip, int server_port){
    return connectsock(server_ip, server_port, SOCK_DGRAM);
    }


  • 相关阅读:
    Objective-C-----协议protocol,代码块block,分类category
    iOS-Core Data 详解
    TCP、UDP详解
    springboot+mybatisplus配置多个mapper路径
    django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb的解决方法
    Django笔记——Eclipse+pydev首个django例子helloworld
    eclipse html插件的下载和安装
    sqlserver往字符串里固定位置插入字符
    在文件夹中直接调用命令提示符
    HTML:如何将网页分为上下两个部分
  • 原文地址:https://www.cnblogs.com/xiaozhuzqh/p/9978669.html
Copyright © 2011-2022 走看看