2017-2018-1 20155330 《信息安全系統設計基礎》第8周學習總結

2017-2018-1 20155330 《信息安全系統設計基礎》第8周學習總結

教材學習內容總結

  • 客戶端一服務器模型中的基本操做是事務。一個客戶端一服務器事務由如下四步組成。html

    1. 當一個客戶端須要服務時,它向服務器發送一個請求,發起一個事務。例如,當Web瀏覽器須要一個文件時,它就發送一個請求給Web服務器。
    2. 服務器收到請求後,解釋它,並以適當的方式操做它的資源。例如,當Web服務器收到瀏覽器發出的請求後,它就讀一個磁盤文件。
    3. 服務器給客戶端發送一個響應,並等待下一個請求。例如,Web服務器將文件發送回客戶端。
    4. 客戶端收到響應並處理它。例如,當Web瀏覽器收到來自服務器的一頁後,就在屏幕上顯示此頁。
  • 對主機而言,網絡市一中I/O設備,是數據源和數據接收方。
  • 一個以太網段(Ethernet segment)包括一些電纜(一般是雙絞線)和一個叫作集線器的小盒子,以太網段一般跨越一些小的區域,例如某建築物的一個房間或者一個樓層。集線器一端接到主機的適配器,而另外一端則鏈接到集線器的一個端口上。集線器不加分辨地將從一個端口上收到的每一個位複製到其餘全部的端口上。所以,每臺主機都能看到每一個位。
  • 每一個以太網適配器都有一個全球惟一的48位地址,它存儲在這個適配器的非易失性存儲器上。一臺主機能夠發送一段位(幀)到這個網段內的其餘任何主機。
  • TCP/IP實際是一個協議族,其中每個都提供不一樣的功能。例如,IP協議提供基本的命名方法和遞送機制,這種遞送機制可以從一臺因特網主機往其餘主機發送包,也叫作數據報(datagram) o IP機制從某種意義上而言是不可靠的,由於,若是數據報在網絡中丟失或者重複,它並不會試圖恢復。UDP ( Unreliable Datagram Protocol,不可靠數據報協議)稍微擴展了IP協議,這樣一來,包能夠在進程間而不是在主機間傳送。TCP是一個構建在IP之上的複雜協議,提供了進程間可靠的全雙工(雙向的)鏈接。
  • 使用命令hostname -i可查詢主機的點分十進制地址:
  • 使用命令naslookup localhost查看域名:
  • www.baidu.com爲例,查看對應IP地址:
  • 進程的優劣:
    • 優勢:一個進程不會不當心覆蓋另外一個進程的虛擬內存。
    • 缺點:獨立的地址空間使進程共享狀態信息變得更加困難,爲共享信息必須使用顯式的IPC(進程間通訊)機制。
  • 基於I/O多路複用的併發編程:
    • 編寫一個echo服務器,它能對用戶從標準輸入鍵人的交互命令作出響應。在這種狀況下,服務器必須響應兩個互相獨立的I/O事件:1>網絡客戶端發起鏈接請求,2)用戶在鍵盤上鍵人命令行。先等待哪一個事件呢?沒有哪一個選擇是理想的。若是在accept中等待一個鏈接請求,就不能響應輸人的命令。相似地,若是在read中等待一個輸人命令,咱們就不能響應任何鏈接請求。
    • 針對這種困境的一個解決辦法就是I/O多路複用(I/O multiplexing)技術。基本的思路就是使用select函數,要求內核掛起進程,只有在一個或多個I/O事件發生後,纔將控制返回給應用程序。
  • I/O多路複用能夠用作併發事件驅動程序的基礎,在事件驅動程序中,某些事件會致使流向前推動。通常的思路是將邏輯流模型化爲狀態機。
  • 線程執行模型
    • 多線程的執行模型在某些方面和多進程的執行模型是類似的。思考圖12-12中的示例。每一個進程開始生命週期時都是單一線程,這個線程稱爲主線程(main thread) o在某一時刻,主線程建立一個對等線程(peer thread),從這個時間點開始,兩個線程就併發地運行。最後,由於主線程執行一個慢速系統調用,例如read或者sleep,或者由於被系統的間隔計時器中斷,控制就會經過上下文切換傳遞到對等線程。對等線程會執行一段時間,而後控制傳遞迴主線程,依次類推。
    • 在一些重要的方面,線程執行是不一樣於進程的。由於一個線程的上下文要比一個進程的上下文小得多,線程的上下文切換要比進程的上下文切換快得多。另外一個不一樣就是線程不像進程那樣,不是按照嚴格的父子層次來組織的。和一個進程相關的線程組成一個對等(線程)池,獨立於其餘線程建立的線程。主線程和其餘線程的區別僅在於它老是進程中第一個運行的線程。對等(線程)池概念的主要影響是,一個線程能夠殺死它的任何對等線程,或者等待它的任意對等線程終止。另外,每一個對等線程都能讀寫相同的共享數據。

課堂測試及課下做業

測試3

基於socket 使用教材的csapp.h csapp.c,實現daytime(13)服務器(端口咱們使用13+後三位學號)和客戶端
服務器響應消息格式是
「客戶端IP:XXXX
服務器實現者學號:XXXXXXXX
當前時間: XX:XX:XX」

一個客戶端至少查詢三次時間的截圖測試截圖

至少兩個客戶端查詢時間的截圖測試截圖
git

課下做業

把課上練習3的daytime服務器分別用多進程和多線程實現成併發服務器並測試
多進程代碼:編程

#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<strings.h>
#include<ctype.h>
#include<errno.h>
#include<sys/wait.h>
#include<errno.h>
#include <time.h>
#define PORT 13330
#define BACKLOG 1
#define MAXRECVLEN 1024
int main(int argc, char *argv[])
{
    char buf[MAXRECVLEN];
    int listenfd, connectfd;  /* socket descriptors */
    pid_t pid; 
    pid_t pids[10]; 
    struct sockaddr_in server; /* server's address information */
    struct sockaddr_in client; /* client's address information */
    socklen_t addrlen;
    /* Create TCP socket */
    if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        /* handle exception */
        perror("socket() error. Failed to initiate a socket");
        exit(1);
    }
 
    /* set socket option */
    int opt = SO_REUSEADDR;
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    bzero(&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(PORT);
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    if(bind(listenfd, (struct sockaddr *)&server, sizeof(server)) == -1)
    {
        /* handle exception */
        perror("Bind() error.");
        exit(1);
    }
    
    if(listen(listenfd, BACKLOG) == -1)
    {
        perror("listen() error. \n");
        exit(1);
    }
    addrlen = sizeof(client);
int i;
    for(i = 0; i< 10;i++){
        pid = fork();
        if(pid > 0){
            continue;
        }
        pids[i] = pid;
}
    while(1){
        if((connectfd=accept(listenfd,(struct sockaddr *)&client, &addrlen))==-1)
          {
            perror("accept() error. \n");
            exit(1);
          }
        struct timeval tv;
        gettimeofday(&tv, NULL);
    time_t t;
    t=time(NULL);
    printf("客戶端IP: %s.  \n",inet_ntoa(client.sin_addr));
    printf("服務器實現者學號:%d\n",20155330);
    printf("當前時間: %s\n",ctime(&t));
    }    
        int iret=-1;
        while(1)
        {
            iret = recv(connectfd, buf, MAXRECVLEN, 0);
            if(iret>0)
            {
                //printf("%s\n", buf);
            }else
            {
                close(connectfd);
                break;
            }
            /* print client's ip and port */
            send(connectfd, buf, iret, 0); /* send to the client welcome message */
        }
    
    close(listenfd); /* close listenfd */
    return 0;
}

測試結果:
瀏覽器

多線程代碼:安全

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<sys/socket.h>
#include<sys/types.h>       //pthread_t , pthread_attr_t and so on.
#include<netinet/in.h>      //structure sockaddr_in
#include<arpa/inet.h>       //Func : htonl; htons; ntohl; ntohs
#include<assert.h>          //Func :assert
#include<string.h>          //Func :memset
#include<unistd.h>          //Func :close,write,read
#include<ctype.h>
#include<arpa/inet.h>
#include <time.h>
#define SOCK_PORT 13330
#define BUFFER_LENGTH 1024
#define MAX_CONN_LIMIT 5    //MAX connection limit

static void Data_handle(void * sock_fd);   

    struct sockaddr_in s_addr_in;
    struct sockaddr_in s_addr_client;
   int sockfd;
int main()
{
    int sockfd_server;
 
    int fd_temp;
    int client_length;

    sockfd_server = socket(AF_INET,SOCK_STREAM,0);  //ipv4,TCP
    assert(sockfd_server != -1);
    memset(&s_addr_in,0,sizeof(s_addr_in));
    s_addr_in.sin_family = AF_INET;
    s_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);  //trans addr from uint32_t host byte order to network byte order.
    s_addr_in.sin_port = htons(SOCK_PORT);          //trans port from uint16_t host byte order to network byte order.

    fd_temp = bind(sockfd_server,(struct scokaddr*)(&s_addr_in),sizeof(s_addr_in));

    if(fd_temp == -1)
    {
        fprintf(stderr,"bind error!\n");
        exit(1);
    }

    fd_temp = listen(sockfd_server,MAX_CONN_LIMIT);

    if(fd_temp == -1)
    {
        fprintf(stderr,"listen error!\n");
        exit(1);
    }

   while(1)
    {
        pthread_t thread_id;
        client_length = sizeof(s_addr_client);
        sockfd = accept(sockfd_server,(struct sockaddr*)(&s_addr_client),&client_length);

    time_t t = time(0); 
        char tmp[64]; 
        strftime( tmp, sizeof(tmp), "%Y/%m/%d %X %A\n\t", localtime(&t) ); 
    send(sockfd,tmp,strlen(tmp),0); 
    close(sockfd);  //close a file descriptor.
        if(sockfd == -1)
        {
            fprintf(stderr,"Accept error!\n");
            continue;                               //ignore current socket ,continue while loop.
        }

        if(pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd)) == -1)
        {
            fprintf(stderr,"pthread_create error!\n");
            break;                                  //break while loop
        }
    }

    //Clear
    int ret = shutdown(sockfd_server,SHUT_WR); //shut down the all or part of a full-duplex connection.
    assert(ret != -1);

    return 0;
}

static void Data_handle(void * sock_fd)
{
    int fd = *((int *)sock_fd);
    int i_recvBytes;
    char data_recv[BUFFER_LENGTH];
    printf("服務器實現者:20155330\n");
    printf("客戶端IP:%s\n",inet_ntoa(s_addr_client.sin_addr)); 
    pthread_exit(NULL);   //terminate calling thread!
}

測試結果:
服務器

教材學習中的問題和解決過程

  • 問題1:多進程和多線程的區別
  • 問題1解決方案:進程是資源分配的最小單位,線程是CPU調度的最小單位;進程編程調試簡單可靠性高,可是建立銷燬開銷大;線程正相反,開銷小,切換速度快,可是編程調試相對複雜。

代碼調試中的問題和解決過程

  • 問題1:編譯多線程代碼失敗。
  • 問題1解決方案:輸入gcc XXX.c -lpthread -o XXX進行編譯。

上週考試錯題總結

  • 錯題1:假設用ADD指令完成C表達式t=a+b的功能,有關條件碼寄存器的說法正確的是()

A.若t==0則ZF=1網絡

B.若t<0,則CF=1多線程

C.若t<0,則SF=1併發

D.若(a<0==b<0)&&(t<0 != a<0), 則OF=1app

E.若(a<0==b<0)&&(t<0 != a<0), 則CF=1

F.leaq指令不影響條件碼寄存器

G.cmp指令不影響條件碼寄存器

  • 理解狀況:ZF爲零標誌,當最近操做得出的結果爲0時,ZF=1。當最近操做致使一個補碼溢出時,OF=1。CF爲進位標誌,當最高位產生進位時,CF=1。t<0,SF=0。
  • 錯題2:假設%rax中的值爲x, %rcx中的值爲y,關於leaq指令,下面正確的()

A.leaq 6(%rax), %rdx; %rdx中值爲6+x

B.leaq 6(%rax), %rdx; %rdx中值爲6x

C.leaq 7(%rax, %rax,8), %rdx; %rdx中值爲9x

D.leaq 7(%rax, %rax,8), %rdx; %rdx中值爲63x

E.leaq 7(%rax, %rax,8), %rdx; %rdx中值爲15x

  • 理解狀況:指令leaq 7(%rax, %rax,8), %rdx中%rdx的值爲7+9x
  • 錯題3:有關exec系列函數,下面說法正確的是()

A.能夠用char[][] 來傳遞argv

B.進程調用了exec系列函數後,pid會變

C.進程調用了exec系列函數後,代碼會改變。

D.system()和exec系列等價。

E.exec系列函數中帶e的要傳入環境變量參數

F.exec系列函數中帶v的要傳入環境變量參數

  • 理解狀況:不能用char[][] 來傳遞argv,結尾的0(null)沒法處理;system=fork+exec+wait;
  • 錯題4:Unix/Linux中經過調用( )能夠獲取子進程PID。

A.getpid()

B.getppid()

C.getcpid()

D.fork()

  • 理解狀況:在父進程中,fork返回子進程的PID。
  • 錯題5:對於圖中內存地址和寄存器的值,下面說法正確的是()
    A.%rax的值是0x100

B.(%rax)的值是0x100

C.(%rax)的值是0x104

D.(%rax)的值是0xFF

E.4(%rax)的值是0xAB

F.(%rax,%rcx,4)的值是0xAB

G.(%rax,%rcx,4)的值是0x104

  • 理解狀況:(rb,ri,s) 操做數值M[R[rb]+R[ri]·s]

    代碼託管

結對及互評

本週結對學習狀況

學習進度條

代碼行數(新增/累積) 博客量(新增/累積) 學習時間(新增/累積) 重要成長
目標 5000行 30篇 400小時
第一週 0/0 1/1 10/10
第二週 63/63 1/2 8/18
第三週 31/94 1/3 18/36
第四周 265/329 1/4 17/53
第五週 106/435 2/6 18/71
第六週 211/646 2/8 21/92
第七週 1420/2066 2/10 17/109
第八週 1061/3127 1/11 17/126

嘗試一下記錄「計劃學習時間」和「實際學習時間」,到期末看看能不能改進本身的計劃能力。這個工做學習中很重要,也頗有用。
耗時估計的公式
:Y=X+X/N ,Y=X-X/N,訓練次數多了,X、Y就接近了。

參考:軟件工程軟件的估計爲何這麼難軟件工程 估計方法

  • 計劃學習時間:18小時

  • 實際學習時間:17小時

參考資料

相關文章
相關標籤/搜索