• 20165310 实验三-并发程序


    20165310 实验三-并发程序

    任务一:学习使用Linux命令wc(1)

    • wc(1)

      • 命令的作用:统计指定文件中的字节数、字数、行数,并将统计结果显示输出。该命令统计指定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所指定文件的总统计数。
      • man方法查询结果:

      幕快照 2018-11-18 上午11.13.2

      • 利用wc命令统计文档text1.txt和text2.txt的字数,并且作为接下来实验正确性的判断标准

        幕快照 2018-11-18 上午11.28.2

    任务二:基于Linux Socket程序设计实现wc(1)服务器和客户端

    • 实验要求

      • 客户端传一个文本文件给服务器
      • 服务器返加文本文件中的单词数
    • 实验程序

      • 客户端:

        #include <stdio.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <string.h>
        #include <pthread.h>
        #pragma comment(lib,"ws2_32.lib")
        
        #define MY_PORT 165310
        #define DEST_IP "172.20.10.4"
        int main()
        {
            SOCKET con_socket;
            struct sockaddr_in remote_addr;
            char buffer[1024];
            char file_name[100];
            char readch;
            int i;
        
            WSADATA wsaDate;
        
            WSAStartup(MAKEWORD(1,1),&wsaDate);
        
            memset(file_name,0,sizeof(file_name));
            memset(buffer,0,sizeof(buffer));
        
            remote_addr.sin_family=AF_INET;
            remote_addr.sin_port=htons(MY_PORT);
            remote_addr.sin_addr.s_addr=inet_addr(DEST_IP);
        
            con_socket=socket(AF_INET,SOCK_STREAM,0);
            if(con_socket==-1)
            {
                printf("Client socket failed!");
                exit(0);
            }
        
            printf("Please Input File Name:
        ");
            scanf("%s", file_name);
        
            if(connect(con_socket,(struct sockaddr*)&remote_addr,sizeof(struct sockaddr))==-1)
            {
                printf("Client connet failed!");
            }
            else
            {
                FILE *fp=fopen(file_name,"r");
                if(fp==NULL)
                {
                    printf("%s File not Found!
        ",file_name);
                }
                else
                {
                    while((readch=fgetc(fp))!=EOF)
                    {
                        if(i<1024)
                        {
                            buffer[i]=readch;
                            i++;
                        }
                        else
                        {
                            i=0;
                            int n=send(con_socket, buffer, 1024, 0);
                            if(n==-1)
                            {
                                printf("Send File Error!
        ");
                            }
                        }
                    }
                    fclose(fp);
                    printf("File:%s Transfer Finished!
        ", file_name);
                }
                fclose(fp);
                long wordscount;
                recv(con_socket, &wordscount, sizeof(long), 0);
                printf("%ld
        ", wordscount);
            }
            closesocket(con_socket);
        
            WSACleanup();
            return 0;
        }
        

      • 服务器:

        #include <stdio.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <string.h>
        
        #define MYPORT 165310
        
        void main()
        {
        	int server_socket, client_socket;
        	struct sockaddr_in my_addr;
        	struct sockaddr_in remote_addr;
        
        	char buffer[BUFSIZ];
        	memset(&my_addr, 0, sizeof(my_addr));
        	my_addr.sin_family=AF_INET;
        	my_addr.sin_addr.s_addr=INADDR_ANY;
        	my_addr.sin_port=htons(MYPORT);
        
        	if((server_socket=socket(PF_INET, SOCK_STREAM, 		0))==-1)	  
            {
        		perror("socket");
        	}
        
        	if(bind(server_socket, (struct sockaddr 			*)&my_addr, sizeof(struct sockaddr))<0)
        	{
        		perror("bind");
        	}
        	listen(server_socket, 5);
        	int addrlen=sizeof(struct sockaddr_in); 
        	while(1)
        	{
        		if((client_socket
                    =accept(server_socket, (struct sockaddr *)&remote_addr, &addrlen))<0)
            	{
        			perror("accept");
        		}
                printf("accept client %s
        ", inet_ntoa(remote_addr.sin_addr));
        		int len, i;
        		long wordscount=0;
        		int flag=1;
        		while(1)
                {
        			if((len=recv(client_socket, buffer, 1024, 				0))>0)
                    {
        				for(i=0; i<len; i++)
                        {
        					if(flag==0)
                            {
        						switch(buffer[i])
                                {
        							case ' ':
        								wordscount++;
        								break;
        							case '
        ':
        								wordscount++;
        								break;
        							case '
        ':
                                        wordscount++;
                                        break;
        							default:
        								break;
        						}
        					}
            		if(buffer[i]== ' ' || buffer[i]=='
        ' || 				buffer[i]=='
        ') flag=1;
           	    	else flag=0;
            			}
        			}
        			if(len<1024) break;
        		}
        		send(client_socket, &wordscount, sizeof(long), 			0);
        		close(client_socket);
        	}
        	close(server_socket);
        }
        
        

    • 实验结果截图

      幕快照 2018-11-13 下午7.18.5

    任务三:多线程实现wc

    • 实验要求

      使用多线程实现wc服务器并使用同步互斥机制保证计数正确

    • 实验程序

      • 客户端:

        #include <stdio.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <string.h>
        #include <pthread.h>
        #pragma comment(lib,"ws2_32.lib")
        
        #define MY_PORT 165310
        #define DEST_IP "172.20.10.4"
        int main()
        {
            SOCKET con_socket;
            struct sockaddr_in remote_addr;
            char buffer[1024];
            char file_name[100];
            char readch;
            int i;
        
            WSADATA wsaDate;
        
            WSAStartup(MAKEWORD(1,1),&wsaDate);
        
            memset(file_name,0,sizeof(file_name));
            memset(buffer,0,sizeof(buffer));
        
            remote_addr.sin_family=AF_INET;
            remote_addr.sin_port=htons(MY_PORT);
            remote_addr.sin_addr.s_addr=inet_addr(DEST_IP);
        
            con_socket=socket(AF_INET,SOCK_STREAM,0);
            if(con_socket==-1)
            {
                printf("Client socket failed!");
                exit(0);
            }
        
            printf("Please Input File Name:
        ");
            scanf("%s", file_name);
        
            if(connect(con_socket,(struct sockaddr*)&remote_addr,sizeof(struct sockaddr))==-1)
            {
                printf("Client connet failed!");
            }
            else
            {
                FILE *fp=fopen(file_name,"r");
                if(fp==NULL)
                {
                    printf("%s File not Found!
        ",file_name);
                }
                else
                {
                    while((readch=fgetc(fp))!=EOF)
                    {
                        if(i<1024)
                        {
                            buffer[i]=readch;
                            i++;
                        }
                        else
                        {
                            i=0;
                            int n=send(con_socket, buffer, 1024, 0);
                            if(n==-1)
                            {
                                printf("Send File Error!
        ");
                            }
                        }
                    }
                    fclose(fp);
                    printf("File:%s Transfer Finished!
        ", file_name);
                }
                fclose(fp);
                long wordscount;
                recv(con_socket, &wordscount, sizeof(long), 0);
                printf("%ld
        ", wordscount);
            }
            closesocket(con_socket);
        
            WSACleanup();
            return 0;
        }
        

      • 服务器:

        #include <stdio.h>
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <string.h>
        #include <pthread.h>
        #pragma comment(lib,"ws2_32.lib")
        pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
        
        #define MY_PORT 165310
        
        typedef struct socket_counter
        {
            SOCKET send_socket;
            char buffer[1024];
        }socket_counter;
        
        void my_wc(socket_counter *my_counter);
        int main()
        {
            SOCKET listen_socket;//声明Socket接口变量
            struct sockaddr_in my_addr;//声明Socket地址变量
            int dummy,rev_length;
            //char buffer[1024];
            char file_name[100];
            pthread_t t;
            socket_counter *my_counter;
        
            WSADATA wsaDate;
        
            WSAStartup(MAKEWORD(1,1),&wsaDate);//启动版本
        
            listen_socket=socket(AF_INET,SOCK_STREAM,0);//声明为IPV4的TCP
        
            my_addr.sin_family=AF_INET;//IPV4
            my_addr.sin_port=htons(MY_PORT);//端口
            my_addr.sin_addr.s_addr=htonl(INADDR_ANY);//可以连接任一电脑
        
            dummy = sizeof(SOCKADDR);
            memset(file_name,0,sizeof(file_name));
        
            if( bind(listen_socket,(struct sockaddr*)&my_addr,sizeof(struct sockaddr))<0)//绑定本地IP与Socket
            {
               printf("Server Bind error!
        ");
            }
        
            if(listen(listen_socket,5)<0)//等待序列,默认队列最多为5个请求
            {
                printf("Server Listen error!
        ");
            }
        
            while(1)
            {
                my_counter->send_socket=accept(listen_socket,NULL,&dummy);//listen函数创建等待队列后,accept函数处理客户端发来的连接请求
                if(my_counter->send_socket==-1)
                {
                    printf("Server Accept failed!
        ");
                    break;
                }
                printf("Accept success!
        ");
                pthread_create(&t, NULL, &my_wc,my_counter);
                pthread_join(&t, NULL);
            }
            closesocket(listen_socket);//依次关闭连接
            WSACleanup();//清除
            return 0;
        }
        void my_wc(socket_counter *my_counter){
            pthread_mutex_lock( &counter_mutex );
            int len, i;
            long wordscount=0;
            int flag=1;
            while(1)
            {
                if((len=recv(my_counter->send_socket, my_counter->buffer, 1024, 0))>0)
                {
                    for(i=0; i<len; i++)
                    {
                        if(flag==0)
                        {
                            switch(my_counter->buffer[i])
                            {
                                case ' ':
                                    wordscount++;
                                    break;
                                case '
        ':
                                    wordscount++;
                                    break;
                                case '
        ':
                                    wordscount++;
                                    break;
                                default:
                                    break;
                            }
                        }
                        if(my_counter->buffer[i]== ' ' || my_counter->buffer[i]=='
        ' || my_counter->buffer[i]=='
        ')
                            flag=1;
                        else
                            flag=0;
                    }
                }
                if(len<1024) break;
            }
            send(my_counter->send_socket, &wordscount, sizeof(long), 0);
            close(my_counter->send_socket);
            pthread_mutex_unlock( &counter_mutex );
        }
        

    • 运行结果截图

      echatIMG17

    • C语言多线程函数

      • 多线程变量声明:pthread_t <变量名>

      • 创建线程的函数pthread_create

        ​ 函数声明:int pthread_create(pthread_t *tidp,const pthread_attr_t *attr,(void*)(*start_rtn)(void*),void *arg);

        ​ 函数说明:类Unix操作系统(Unix、Linux、Mac OS X等)的创建线程的函数。它的功能是创建线程(实际上就是确定调用该线程函数的入口点),在线程创建以后,就开始运行相关的线程函数。表示成功,返回0;表示出错,返回表示-1。

        ​ 参数说明:第一个参数为指向线程标识符的指针。第二个参数用来设置线程属性。第三个参数是线程运行函数的起始地址。最后一个参数是运行函数的参数。

      • 线程回收函数pthread_join:

        ​ 函数声明: int pthread_join(pthread_t thread, void **retval);

        ​ 函数说明:以阻塞的方式等待thread指定的线程结束。当函数返回时,被等待线程的资源被收回。如果线程已经结束,那么该函数会立即返回。 0代表成功。 失败,返回的则是错误号。

        ​ 参数说明:第一个参数为线程标识符,即线程ID,标识唯一线程。第二个参数为 用户定义的指针,用来存储被等待线程的返回值。

      • 互斥锁函数pthread_mutex_lock

        ​ 函数声明:int pthread_mutex_lock(pthread_mutex_t *mutex);

        ​ 函数说明:线程调用该函数让互斥锁上锁,如果该互斥锁已被另一个线程锁定和拥有,则调用该线程将阻塞,直到该互斥锁变为可用为止。 成功完成之后会返回零。其他任何返回值都表示出现了错误。

    遇到问题与解决方法

    • pthread_create函数传参只能传一个值,然而程序中需要传入两个值

      解决方法:利用C语言结构体,传入结构体作为唯一参数

    • 计算出单词个数不正确,少于正确值

      解决方法:只计算了空格,没有计算' '、' '等特殊字符

  • 相关阅读:
    PHP UPLOAD 实现附件上传
    迁移服务器小记
    php TP5.1 将session 存入Redis
    js 精度问题的处理方法
    Aspect 浏览器插件
    JavaScript 构建工具 的发展和变化
    js input 保留1位小数
    如何使用adb 安装 apk应用
    php精度计算问题
    [Typescript] 89. Hard Currying 1
  • 原文地址:https://www.cnblogs.com/atbaoi/p/9977653.html
Copyright © 2020-2023  润新知