2017-2018-1 20155214 《信息安全系统设计基础》
实验三 并发程序
实验要求
任务一
学习使用Linux命令wc(1)
基于Linux Socket程序设计实现wc(1)服务器(端口号是你学号的后6位)和客户端
客户端传一个文本文件给服务器
服务器返加文本文件中的单词数
任务二
使用多线程实现wc服务器并使用同步互斥机制保证计数正确
上方提交代码
下方提交测试
对比单线程版本的性能,并分析原因
任务三
交叉编译多线程版本服务器并部署到实验箱中
PC机作客户端测试wc服务器
实验背景
- wc
统计指定文件中的字节数、字数、行数,并将统计结果显示输出。该命令统计指定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所指定文件的总统计数。
-w
统计字数。一个字被定义为由空白、跳格或换行字符分隔的字符串。
伪代码
//客户端
......
打开文件
while(文件不为空){
将文件读入缓存区
将缓冲区内容发送至服务器
}
接收服务器返回的字数
......
//服务器
......
打开文件
while(当客户端传输字节不为0){
调用wc函数计算接收缓存区中的字数
将缓存区里的内容写入文件
}
将统计的文件字数返回给客户端
......
多线程实现
- 线程创建函数CreateThread(),属于API函数;
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, //指向结构体SECURITY_ATTRIBUTES的指针,表示指定新建线程的安全属性
DWORD dwStackSize, //指定线程初始化时地址空间的大小
LPTHREAD_START_ROUTINE lpStartAddress,//指定该线程的线程函数的地址
LPVOID lpParameter,//将要传递给新建线程的命令行参数
DWORD dwCreationFlags, //指定新建线程创建后是否立即执行
LPDWORD lpThreadId ); 表示新建线程的ID号
-
pthread_create调用成功以后,新线程和老线程谁先执行,谁后执行用户是不知道的,这一块取决与操作系统对线程的调度,如果我们需要等待指定线程结束,需要使用pthread_join函数,这个函数实际上类似与多进程编程中的waitpid。
-
gcc编译时需要加上
-lpthread
,要不然会报错
多线程的同步互斥
-
通过信号量控制。信号量本质上是一个非负数的整数计数器,它也被用来控制对公共资源的访问。当公共资源增加的时候,调用信号量增加函数sem_post()对其进行增加,当公共资源减少的时候,调用函数sem_wait()来减少信号量。
-
关键代码
void *thread(void *vargp){
time_t lt;
tm *local;
char sbuf[MAXLINE];
int count = 0;
char *fp = fopen("test.txt","wb");
char rbuf[MAXLINE];
int connfd = *((int*)vargp);
free(vargp);
pthread_detach(pthread_self());
/*lt = time(NULL);
local = localtime(<);
strftime(sbuf,64,"%Y-%m-%d %H:%M:%S",local);
send(connfd,sbuf,MAXLINE,0);
*/
while(recv(connfd,rbuf,MAXLINE,0)){
//printf("%d\\n",recv(connfd,rbuf,MAXLINE,0));
fputs(rbuf,fp);
count += wc(rbuf);
bzero(rbuf,sizeof(rbuf));
}
//printf("传输成功!,该文件单词数共%d\\n!",count);
fclose(fp);
itoa(count,sbuf);
//send(connfd,sbuf,MAXLINE,0);
printf("该文件单词数为%s!\\n",sbuf);
close(connfd);
return NULL;
}
多线程编程的目的,就是"最大限度地利用CPU资源",当某一线程的处理不需要占用CPU而只和I/O,OEMBios等资源打交道时,让需要占用CPU资源的其它线程有机会获得CPU资源。每个程序执行时都会产生一个进程,而每一个进程至少要有一个主线程。这个线程其实是进程执行的一条线索,除了主线程外你还可以给进程增加其它的线程,也即增加其它的执行线索,由此在某种程度上可以看成是给一个应用程序增加了多任务功能。当程序运行后,您可以根据各种条件挂起或运行这些线程,尤其在多CPU的环境中,这些线程是并发运行的。多线程就是在一个进程内有多个线程。从而使一个应用程序有了多任务的功能。
- 通过命令行
/usr/local/toolchain/toolchain4.3.2/bin/arm-none-linux-gnuenbi-gcc -c dateserveri.c
和/usr/local/toolchain/toolchain4.3.2/bin/arm-none-linux-gnuenbi-gcc -static -o dateserveri dateserveri.o csapp.a -lpthread
即可实现交叉编译。