20175323 信息安全系统设计基础 实验三 并发程序
任务一
- 实验要求
- 学习使用Linux命令wc(1)
- 基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
- 客户端传一个文本文件给服务器
- 服务器返加文本文件中的单词数
- 实验步骤
使用man命令学习查看wc指令,结果如下:
通过man命令我们很快知道接下来的实验中需要用到的便是-w参数——统计字数,仔细查看发现这里他们将字定义为由空白、跳格或换行字符分隔的字符串;
代码如下
客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define MYPORT 175323
void 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
", wordscount);
close(clientfd);
}
服务器
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define MYPORT 175323
void 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
", 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 '
':
wordscount++;
break;
case '
':
wordscount++;
break;
default:
break;
}
}
if(buffer[i]== ' ' || buffer[i]=='
' || buffer[i]=='
') flag=1;
else flag=0;
}
}
if(len<1024) break;
}
send(clientfd, &wordscount, sizeof(long), 0);
close(clientfd);
}
close(serverfd);
}
实验截图
任务二
- 实验要求
- 使用多线程实现wc服务器并使用同步互斥机制保证计数正确
- 上方提交代码
- 下方提交测试
- 对比单线程版本的性能,并分析原因
- 实验步骤
通过man命令,可以找到“pthread_create()”函数来创建进程
pthread库不是Linux系统默认的库,连接时需要使用静态库libpthread.a,在编译中要加-lpthread
参数
客户端
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define MYPORT 175323
void 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
", wordscount);
close(clientfd);
}
服务器
#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>
#define MYPORT 175323
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
int serverfd, clientfd;
char buffer[BUFSIZ];
void *wc(void *m){
pthread_mutex_lock( &counter_mutex );
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 '
':
wordscount++;
break;
case '
':
wordscount++;
break;
default:
break;
}
}
if(buffer[i]== ' ' || buffer[i]=='
' || buffer[i]=='
')
flag=1;
else
flag=0;
}
}
if(len<1024)
break;
}
send(clientfd, &wordscount, sizeof(long), 0);
close(clientfd);
pthread_mutex_unlock( &counter_mutex );
return NULL;
}
void main(){
pthread_t t;
char arg[30];
struct sockaddr_in my_addr;
struct sockaddr_in remote_addr;
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
", inet_ntoa(remote_addr.sin_addr));
pthread_create(&t, NULL, &wc, NULL);
pthread_join(&t, NULL);
}
close(serverfd);
}
实验截图
任务三
- 实验要求
- 交叉编译多线程版本服务器并部署到实验箱中
- PC机作客户端测试wc服务器
- 提交测试截图
该部分尚未完成