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这个错误。此时,目前我只能通过改变端口号来再次运行代码。