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

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

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

目录


一、任务一


(一)要求

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

(二)实验步骤

  • 使用man wc查看wc(1)

    1047870-20181117230817952-872538009.png

  • wc命令

参数 用法
-c 统计字节数
-l 统计行数
-m 统计字符数,不能与 -c 连用
-w 统计字数,一个字被定义为由空白、跳格或换行字符分隔的字符串
-L 打印最长行的长度
-help 显示帮助信息
--version 显示版本信息
  • socket编程模型
    1047870-20181117234044187-1388677220.png

(三)代码实现

  • 客户端
#include 
#include
#include
#include
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")#define MY_PORT 165226#define DEST_IP "10.1.1.232"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 165226typedef 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 );}

(四)结果

  • 服务器端

    1047870-20181117232521602-1689563875.png

  • 客户端

    1047870-20181117232537607-966159744.png

二、任务二


(一)要求

使用多线程实现wc服务器并使用同步互斥机制保证计数正确
上方提交代码
下方提交测试

(二)实验步骤:

服务器代码需要增加两个功能

  • 增加多线程
  • 使用同步互斥

    只需更改服务器端代码

(三)代码实现

  • 服务器端
#include 
#include
#include
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;#define MY_PORT 165315typedef 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 );

(四)运行结果

1047870-20181117233240645-672362321.png

(五)实验分析

相比单线程,多线程运行时可以同时多个客户端一起给服务器传文件效率更高

三、实验过程中遇到的问题及解决


  • 问题1:Fatal error: stdafx.h : No such file or directory
  • 问题1解决方案:建工程自带,将其删除即可;或者是手动添加头文件

  • 问题 2:
||=== 生成: Debug in ccc (compiler: GNU GCC Compiler) ===|obj\Debug\main.o||In function `Z10ThreadprocPv@4':|D:\code\ccc\main.cpp|16|undefined reference to `recv@16'|obj\Debug\main.o||In function `main':|D:\code\ccc\main.cpp|28|undefined reference to `WSAStartup@8'|D:\code\ccc\main.cpp|30|undefined reference to `socket@12'|D:\code\ccc\main.cpp|33|undefined reference to `WSAGetLastError@0'|D:\code\ccc\main.cpp|40|undefined reference to `inet_addr@4'|D:\code\ccc\main.cpp|41|undefined reference to `htons@4'|D:\code\ccc\main.cpp|43|undefined reference to `bind@12'|D:\code\ccc\main.cpp|49|undefined reference to `listen@8'|D:\code\ccc\main.cpp|56|undefined reference to `accept@12'|D:\code\ccc\main.cpp|62|undefined reference to `htons@4'|D:\code\ccc\main.cpp|62|undefined reference to `inet_ntoa@4'|||=== Build 失败了: 11 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===
  • 问题2解决方案:手动添加“libws2_32.a”到链接器中。

  • 问题3:出现error C4996:’fopen’问题
  • 问题3解决方案:编辑预处理器(添加“_CRT_SECURE_NO_WAR NINGS”)

四、实验感想


  • 本次实验学习了如何使用wc指令,同时分别采用单线程和多线程来实现服务器和客户端之间的信息传输。
  • 对TCP通信过程有了更深的理解,并熟练掌握了Socket编程,同时复习了C语言编程,复习了读取文件、多线程、互斥等知识点。

转载于:https://www.cnblogs.com/musea/p/9976409.html

你可能感兴趣的文章
Spring Data JPA Batch Insertion
查看>>
UEditor自动调节宽度
查看>>
JAVA做验证码图片(转自CSDN)
查看>>
Delphi TServerSocket,TClientSocket实现传送文件代码
查看>>
JS无聊之作
查看>>
Mac上搭建ELK
查看>>
443 Chapter7.Planning for High Availability in the Enterprise
查看>>
框架和语言的作用
查看>>
unidac连接ORACLE免装客户端驱动
查看>>
Cygwin + OpenSSH FOR Windows的安装配置
查看>>
咏南中间件支持手机客户端
查看>>
fastscript增加三方控件之二
查看>>
Windows Vista RTM 你准备好了么?
查看>>
Tensorflow Serving 模型部署和服务
查看>>
Java Web开发详解——XML+DTD+XML Schema+XSLT+Servlet 3.0+JSP 2.2深入剖析与实例应用
查看>>
topcoder srm 680 div1 -3
查看>>
具体数学第二版第四章习题(1)
查看>>
高效前端优化工具--Fiddler入门教程
查看>>
【翻译】我钟爱的HTML5和CSS3在线工具
查看>>
Java多线程学习(吐血超详细总结)
查看>>