20165310 实验三-并发程序

Posted atbaoi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20165310 实验三-并发程序相关的知识,希望对你有一定的参考价值。

20165310 实验三-并发程序

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

  • wc(1)

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

    技术分享图片

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

      技术分享图片

任务二:基于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);
      }
      

      ?

  • 实验结果截图

    技术分享图片

任务三:多线程实现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 );
      }

      ?

  • 运行结果截图

    技术分享图片

  • 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语言结构体,传入结构体作为唯一参数

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

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

以上是关于20165310 实验三-并发程序的主要内容,如果未能解决你的问题,请参考以下文章

2018-2019-120165226_20165310_20165315 实验四 外设驱动程序设计

20165310 Java实验四 《Android程序设计》

2018-2019-1 20165226_20165310_20165318 实验四 外设驱动程序设计

2018-2019-1 20165201 实验三 并发程序

2019-2020-1 20175304 20175303 20175327 20175335 实验三-并发程序

2018-2019-1 20165311《信息安全系统设计基础》实验三 并发程序