2018-2019-1 20165315 实验三 实时系统

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

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

实验步骤

  • 使用man wc命令查看wc(1)

wc命令详解:

  • 语法:wc [选项] 文件
  • 选项含义
    • -c:统计字节数
    • -l:统计行数
    • -w:统计字数
  • wc代码实现
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 '\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;elseflag=0;}}if(len<1024) break;}send(my_counter->send_socket, &wordscount, sizeof(long), 0);close(my_counter->send_socket);pthread_mutex_unlock( &counter_mutex );
}
  • 实现文件传输功能

结合我们在网络安全编程基础中学习的内容,我们知道客户端和服务器的通信过程如下:

  • 完善代码

服务器端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>#define MYPORT 165315void main(){
int serverfd, clientfd;
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((serverfd=socket(PF_INET, SOCK_STREAM, 0))==-1){
perror("socket");
}if(bind(serverfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))<0){
perror("bind");
}
listen(serverfd, 5);
int addrlen=sizeof(struct sockaddr_in);
while(1){
if((clientfd=accept(serverfd, (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(clientfd, buffer, 1024, 0))>0){
for(i=0; i<len; i++){
if(flag==0){
switch(buffer[i]){
case ' ':
wordscount++;
break;
case '\n':
wordscount++;
break;
case '\r':
wordscount++;
break;
default:
break;
}
}
if(buffer[i]== ' ' || buffer[i]=='\n' || buffer[i]=='\r') flag=1;
else flag=0;
}
}
if(len<1024) break;
}
send(clientfd, &wordscount, sizeof(long), 0);
close(clientfd);
}
close(serverfd);
}

客户端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>#define MYPORT 165315void main(){
int clientfd;
struct sockaddr_in remote_addr;
char buffer[BUFSIZ];
memset(&remote_addr, 0 , sizeof(remote_addr));
remote_addr.sin_family=AF_INET;
remote_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
remote_addr.sin_port=htons(MYPORT);if((clientfd=socket(PF_INET,SOCK_STREAM,0))<0){
perror("socket");
}if(connect(clientfd, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr))<0){
perror("connect");
}int len;
FILE *fp;
char path[20];
gets(path);
fp=fopen(path, "r");
char readch;
int i=0;
while((readch=fgetc(fp))!=EOF){
if(i<1024){
buffer[i]=readch;
i++;
}
else{
i=0;
int n=send(clientfd, buffer, 1024, 0);
}
}
fclose(fp);
if(i!=0) send(clientfd, buffer, i, 0);
long wordscount;
recv(clientfd, &wordscount, sizeof(long), 0);
printf("%ld\n", wordscount);
close(clientfd);
}

运行结果

客户端:

服务器端:

任务二 多线程实现wc功能

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

实验步骤

  • 客户端代码不需要改变,只需要改变服务器代码
  • 服务器代码需要增加两个功能
    • 增加多线程
    • 使用同步互斥
  • 代码实现

服务器端:

#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 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的TCPmy_addr.sin_family=AF_INET;//IPV4my_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<len; i++){if(flag==0){switch(my_counter->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;elseflag=0;}}if(len<1024) break;}send(my_counter->send_socket, &wordscount, sizeof(long), 0);close(my_counter->send_socket);pthread_mutex_unlock( &counter_mutex );
}

客户端:

#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 165315
#define DEST_IP "127.0.0.1"
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;
}

实验分析

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

实验结果

实验中出现的问题

  • 客户端始终无法与服务器端连接上

解决过程:
经过反复调试代码排查,发现竟然是客户端和服务器端的端口号设置的不同导致的(客户端设置的是165315,服务器端设置的是5315),这样的小错误耗费了大半个小时的时间,实在是非常不值得...

  • 编译过程没有问题,但是在在运行过程中出现段错误(Segmentation Fault)

解决过程:
经过上网查询,在一篇博客中找到了错误的原因:指针使用错误

实验感想

本次实验重点在实现Linux下wc指令的功能,即统计文本单词的数量,并分别用单线程和多线程、客户端和服务器端之间的传输实现,有一定难度,结合了网络安全编程基础的知识,这让我更加感受到了这学期课程之间的融会贯通。在同组同学的相互帮助之下,借鉴了网路安全编程基础的代码,终于成功实现,也是有一定成就感的。
但是在实验过程中,也犯了大大小小很多错误,导致差点想放弃,但是在同组同学的鼓励下,我们还是坚持到了最后,坚持就是胜利!

转载于:https://www.cnblogs.com/yh666/p/9976044.html

2018-2019-1 20165315 实验三 实时系统相关推荐

  1. 2017-2018-1 20155222实验三 实时系统

    2017-2018-1 20155222实验三 实时系统 1.学习使用Linux命令wc 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文 ...

  2. 2018-2019-1 20165305 实验三 实时系统

    实验三 实时系统 码云链接 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文本文件给服 ...

  3. 20145208 20145230 20145235 《信息安全系统设计基础》实验三 实时系统的移植

    20145208 20145230 20145235 <信息安全系统设计基础>实验三 实时系统的移植 转载于:https://www.cnblogs.com/20145235litao/p ...

  4. 2017-2018-1 20155209 实验三 实时系统

    2017-2018-1 20155209 实验三 实时系统 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端传一个文 ...

  5. 2017-2018-1 20155223 实验三 实时系统

    2017-2018-1 20155223 实验三 实时系统 实验1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端 客户端 ...

  6. 2018-2019-1 20165219 实验三 实时系统

    2018-2019-1 20165219 实验三 实时系统 任务一 实验要求 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户 ...

  7. 2017-2018-1 20155320 实验三——实时系统

    2017-2018-1 20155320 实验三--实时系统 实验三-并发程序-1 学习使用Linux命令wc(1) 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的> ...

  8. 2017-2018-11 20155307刘浩 20155338常胜杰 20155335俞昆 实验三 实时系统实验报告

    2017-2018-11 20155307刘浩 20155338常胜杰 20155335俞昆 实验三 实时系统 实验目的 实验一: 学习使用Linux命令wc(1) 基于Linux Socket程序设 ...

  9. 2017-2018-1 20155332实验三 实时系统报告

    20155332 实验三 任务一: 1.学习使用Linux命令wc(1)2.基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端3.客户端传一个文本文件给服务器4 ...

最新文章

  1. vba mysql odbc_使用VBA+ODBC+MySQL实现Excel网络版
  2. Ubuntu Server中怎样卸载keepalived
  3. mysql 二进制日志详解_Mysql二进制日志详解
  4. mysql源码启动_Mysql源码安装、配置、初始化及启动
  5. 本地正常,部署放在IIS服务器上面偶尔会出现 列不属于表Table,因为多客户并发造成那个的问题
  6. Android移植的Box2D
  7. c语言-命令行选项_EWSTM8系列教程06_工程节点选项配置(一)
  8. 微信抢红包代码 python_python实现红包裂变算法
  9. NKOJ2317 英语四六级考试
  10. 接手一手机android app维护 如何快速进入,快速上手Android开发,学会这三点就够了!...
  11. c++ 的 stl模板库_C ++中的标准模板库(STL)
  12. 7教程统计意义_SPSS混合线性模型在生物医药统计中的应用——杏花开生物医药统计...
  13. 测试创新——用户体验测试(UAT)
  14. pdf 加深 扫描件_扫描文字字体如何加深 pdf扫描件字体加深
  15. 惠斯通电桥你知道怎么用吗?
  16. 系统集成项目管理工程师11《项目风险管理》
  17. colorbox加载ajax调用的html页面,ColorBox
  18. 看病(版权所有翻版必究)
  19. python对整数进行因数分解_浅谈将一个正整数分解质因数的逻辑思维和Python开发设计...
  20. Linux 系统编程笔记-(1)基本概念

热门文章

  1. 面试准备系列01----面试中的链表题目汇总
  2. Linux常用命令(第二版) --压缩解压缩命令
  3. android源码查看源码的版本
  4. Altium Designer 09 使用要点:电气连接工具
  5. C#之基本知识和语法3 - 数据类型
  6. Java实现插值查找算法 Insert search
  7. 数字语音信号处理学习笔记——语音信号的短时时域分析(2)
  8. 想要成为软件开发中的王者,需要明白的 21 条准则
  9. C语言中fun的功能是将字符串,下列给定的程序中,fun()函数的功能是:将p所指字符串中......
  10. 新编C语言程序设计入门,新编C语言程序设计教程(本科)第3篇.pdf