2017-2018-1 20155306 《信息安全系统设计基础》第8周课上测试+课下实践

2017-2018-1 20155306 《信息安全系统设计基础》第8周课上测试+课下实践

课上任务三:

基于socket 使用教材的csapp.h csapp.c,实现daytime(13)服务器(端口我们使用13+后三位学号)和客户端
 服务器响应消息格式是
“
客户端IP:XXXX
服务器实现者学号:XXXXXXXX
当前时间: XX:XX:XX
”
上方提交代码
 提交一个客户端至少查询三次时间的截图测试截图
 提交至少两个客户端查询时间的截图测试截图

课下实践一:(任务二课上已提交)

1 完成家庭作业4.47,4.48,4.49
2 相应代码反汇编成X86-64汇编
3 把上述X86-64汇编翻译成Y86汇编,并给出相应机器码

发操作过程、测试、问题解决过程博客链接

4.47

取指阶段 icode:ifun =M1[PC]= D:0
valP<-PC+1//下一条指令地址  
译码阶段:valB <- R[%ebp]//得到ebp的值,也就是新的栈指针esp的值  
执行阶段:valE <- valB+4//栈指针的值加4  
访存阶段:valM <-M4[valB]//读ebp中的值  
写回阶段:R[%esp] <- valE //把更新后的指针赋值给esp  
R[%ebp] <- valM//弹出的ebp的值 

4.48

取指阶段:icode:ifun = M1[PC] = C:0 
rA:rB <- M1[PC+1]
valC <- M4[PC+2]
valP <- PC+6   
译码阶段:valB <- R[rB]   
执行阶段:valE <- valB+valC
SetCC
访存阶段 
写回阶段  R[rB] <- valE 

课下实践二:

把课上练习3的daytime服务器分别用多进程和多线程实现成并发服务器并测试
提交博客链接
  • 前面实现的daytime服务器使用的单进程同步模型,处理完一个连接后才能处理下一个连接.若使用多进程实现,我们可以每个连接fork一个子进程来进行处理。
    主要代码如下:
  for ( ; ; )  
    {  
        // 阻塞在accept函数上, 等待客户进行连接  
        // 当连接建立后, 返回一个已连接描述符  
        connfd = accept(listenfd, NULL, NULL);  
        // fork会创建一个子进程, 并且会有2个返回值, 在子进程中返回0  
        // 在父进程中会返回子进程的pid  
        if((childpid = fork()) == 0)   
        {//这里表明在子进程中了  
            // '关闭'监听套接字, 注意这并不会真正关闭  
            // 因为系统对每个套接字都维护着一个引用计数, fork后监听套接字被  
            // 父子进程共享, 其引用计数为2, 真正的关闭发生在引用计数为1的时候  
            // 这里仅仅是将监听套接字的引用计数减1  
            close(listenfd);  
            // 获取当前时间, 并转换为直观可读的时间格式  
            ticks = time(NULL);  
            snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));  
            // 把时间发送给客户, 然后关闭当前连接  
            write(connfd, buff, strlen(buff));  
            sleep(10);  
            close(connfd);  
            exit(0);  
        }  
        // 同上面一样, 这并不会导致服务端发送FIN分节  
        // 除非子进程先对已连接套接字进行了关闭操作  
        close(connfd);  
    } 

  • 查阅资料,得知多进程方式使用fork生成子进程存在一些问题。首先,fork占用大量的资源,内存映像要从父进程拷贝到子进程,所有描述符要在子进程中复制;其次,fork子进程后,需要用进程间通信在父进程和子进程间传递信息,从子进程返回信息给父进程需要做较多的工作。
  • 多线程有助于解决以上两个问题。
    线程是进程内的独立执行实体和调度单元,又称为“轻量级”进程(lightwightprocess);创建线程比进程快10~100倍。一个进程内的所有线程共享相同的内存空间、全局变量等信息(这种机制又带来了同步问题)。

相关函数:

  • pthread_create()函数用于创建新线程。当一个程序开始运行时,系统产生一个称为初始线程或主线程的单个线程,额外的线程需要由pthread_create()函数创建。
  • pthread_join()函数用于等待一个线程终止。
  • pthread_detach()函数将指定的线程变成脱离的。
  • pthread_exit()函数用于终止当前线程,并返回状态值。如果当前线程是可汇合的,将保留线程id和退出状态供pthread_join()函数调用。
    **tcp多线程并发服务器框架: **

建立一个TCP并发服务器核心代码:

//获得一个已经建立的连接     
        connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);                                
        if(connfd < 0)  
        {  
            perror("accept this time");  
            continue;  
        }  
          
        
        if(connfd > 0)  
        {  
            //由于同一个进程内的所有线程共享内存和变量,因此在传递参数时需作特殊处理,值传递。  
            pthread_create(&thread_id, NULL, (void *)client_fun, (void *)connfd);  //创建线程  
            pthread_detach(thread_id); // 线程分离,结束时自动回收资源  
        }  

遇到的问题:

问题1:出现如下图错误:

解决:经过查询,知道是因为没有由于csapp.c 未被导入,但是网上各种导入到usr/lib的方法都尝试过,但是不行。后来找到一种方法:
gcc csapp.c XX.c -o xx 来把csapp.c csapp.h与程序放在同一个目录下,一起进行编译。运行成功。

问题二:出现下图错误:

解决:在编译代码时,要加上 -lpthread 才可以通过编译。
问题三:在进行连接时,出现端口被占用的情况,出现错误提示:Open_listenfd error: Address already in use

解决:要注意在运行代码时,如果先ctrl+c结束服务器端程序的话,再次启动服务器就会出现Address already in use这个错误。此时,目前我只能通过改变端口号来再次运行代码。

参考资料:

多线程并发服务器编程

Linux网络编程——tcp并发服务器(多线程)

多进程同步模型的daytime服务器

posted on 2017-11-12 23:01  20155306  阅读(124)  评论(0编辑  收藏  举报

导航