2017-2018-1 20155214 《信息安全系統設計基礎》實驗三 並發程序
2017-2018-1 20155214 《信息安全系統設計基礎》
實驗三 並發程序
實驗要求
任務一
學習使用Linux命令wc(1)
基於Linux Socket程序設計實現wc(1)服務器(端口號是你學號的後6位)和客戶端
客戶端傳一個文本文件給服務器
服務器返加文本文件中的單詞數
任務二
使用多線程實現wc服務器並使用同步互斥機制保證計數正確
上方提交代碼
下方提交測試
對比單線程版本的性能,並分析原因
任務三
交叉編譯多線程版本服務器並部署到實驗箱中
PC機作客戶端測試wc服務器
實驗背景
- wc
統計指定文件中的字節數、字數、行數,並將統計結果顯示輸出。該命令統計指定文件中的字節數、字數、行數。如果沒有給出文件名,則從標準輸入讀取。wc同時也給出所指定文件的總統計數。
-w
統計字數。一個字被定義為由空白、跳格或換行字符分隔的字符串。
偽代碼
//客戶端
......
打開文件
while(文件不為空){
將文件讀入緩存區
將緩沖區內容發送至服務器
}
接收服務器返回的字數
......
//服務器
......
打開文件
while(當客戶端傳輸字節不為0){
調用wc函數計算接收緩存區中的字數
將緩存區裏的內容寫入文件
}
將統計的文件字數返回給客戶端
......
碼雲鏈接
https://gitee.com/besti155214/BESTI.IS.ISSDB.20155214/tree/exp0/exp0/src/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
即可實現交叉編譯。
2017-2018-1 20155214 《信息安全系統設計基礎》實驗三 並發程序