博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
20165310 实验三-并发程序
阅读量:4703 次
发布时间:2019-06-10

本文共 7410 字,大约阅读时间需要 24 分钟。

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 
      #include
      #include
      #include
      #include
      #include
      #include
      #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:\n"); 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!\n",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!\n"); } } } fclose(fp); printf("File:%s Transfer Finished!\n", file_name); } fclose(fp); long wordscount; recv(con_socket, &wordscount, sizeof(long), 0); printf("%ld\n", wordscount); } closesocket(con_socket); WSACleanup(); return 0;}

    • 服务器:

      #include 
      #include
      #include
      #include
      #include
      #include
      #define MYPORT 165310void 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\n", 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

  • 实验结果截图

    幕快照 2018-11-13 下午7.18.5

任务三:多线程实现wc

  • 实验要求

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

  • 实验程序

    • 客户端:

      #include 
      #include
      #include
      #include
      #include
      #include
      #include
      #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:\n"); 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!\n",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!\n"); } } } fclose(fp); printf("File:%s Transfer Finished!\n", file_name); } fclose(fp); long wordscount; recv(con_socket, &wordscount, sizeof(long), 0); printf("%ld\n", wordscount); } closesocket(con_socket); WSACleanup(); return 0;}

    • 服务器:

      #include 
      #include
      #include
      #include
      #include
      #include
      #include
      #pragma comment(lib,"ws2_32.lib")pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;#define MY_PORT 165310typedef 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!\n"); } if(listen(listen_socket,5)<0)//等待序列,默认队列最多为5个请求 { printf("Server Listen error!\n"); } while(1) { my_counter->send_socket=accept(listen_socket,NULL,&dummy);//listen函数创建等待队列后,accept函数处理客户端发来的连接请求 if(my_counter->send_socket==-1) { printf("Server Accept failed!\n"); break; } printf("Accept success!\n"); 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
      buffer[i]) { case ' ': wordscount++; break; case '\n': wordscount++; break; case '\r': wordscount++; break; default: break; } } if(my_counter->buffer[i]== ' ' || my_counter->buffer[i]=='\n' || my_counter->buffer[i]=='\r') 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语言结构体,传入结构体作为唯一参数

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

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

转载于:https://www.cnblogs.com/atbaoi/p/9977653.html

你可能感兴趣的文章
yahoo的30条优化规则
查看>>
[CCF2015.09]题解
查看>>
[NYIST15]括号匹配(二)(区间dp)
查看>>
json_value.cpp : fatal error C1083: 无法打开编译器生成的文件:No such file or directory
查看>>
洛谷 P1101 单词方阵
查看>>
Swift DispatchQueue
查看>>
C#和JAVA 访问修饰符
查看>>
小甲鱼OD学习第1讲
查看>>
HDU-1085 Holding Bin-Laden Captive-母函数
查看>>
php提示undefined index的几种解决方法
查看>>
LRJ
查看>>
Struts2环境搭建
查看>>
Linux: Check version info
查看>>
stl学习之测试stlen,cout等的运行速度
查看>>
魔戒三曲,黑暗散去;人皇加冕,光明归来
查看>>
Error和Exception
查看>>
Python和Singleton (单件)模式[转载]
查看>>
httpclient设置proxy与proxyselector
查看>>
IT常用单词
查看>>
拓扑排序
查看>>