2017-2018-1 20155308 《信息安全系统设计基础》第八周课上+课下测试
课堂测试
任务一
参考 http://www.cnblogs.com/rocedu/p/6766748.html#SECCLA 在Linux下完成“求命令行传入整数参数的和”
测试代码传入自己的8位学号
上方提交代码
附件提交运行测试截图
- 实验过程
#include <stdio.h>
int main( int argc, char *argv[] )
{
int i;
int sum;
for( i=1;i<argc;i++ )
{
sum +=atoi(argv[i]);//atoi()函数把字符串转换成整型数
}
printf("%d",sum);
return 0;
}
- 实验中问题
这个题是比较简单的,但是我在提交的过程中出现了错误,然后就没有提交上。
这个代码中有一个注意事项:即调用“atoi()函数把字符串转换成整型数”。如果没有调用这个函数,就会出现这个情况。
就是因为类型没有转换!
任务二
把第一个练习中的代码在X86-64(Ubuntu)中反汇编,给出汇编代码和机器码的截图
把X86-64汇编翻译成Y86-64汇编,并给出相应机器码的截图(使用附件中的Y86-64模拟器)
- 实验过程
- 首先查看汇编代码
- 反编译查看机器代码
- Y86-64汇编
0x0000: | Disassembly of section .text:
|
0x0000: | 00000000 <bubble_p>:
0x0000: | 0: 56 push %esi
0x0000: | 1: 53 push %ebx
0x0000: | 2: 8b 44 24 10 mov 0x10(%esp),%eax
0x0000: | 6: 8b 54 24 0c mov 0xc(%esp),%edx
0x0000: | a: 8d 70 ff lea -0x1(%eax),%esi
0x0000: | d: 85 f6 test %esi,%esi
0x0000: | f: 7e 2d jle 3e <bubble_p+0x3e>
0x0000: | 11: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi
0x0000: | 18: 31 c0 xor %eax,%eax
0x0000: | 1a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
0x0000: | 20: 8b 4c 82 04 mov 0x4(%edx,%eax,4),%ecx
0x0000: | 24: 8b 1c 82 mov (%edx,%eax,4),%ebx
0x0000: | 27: 39 d9 cmp %ebx,%ecx
0x0000: | 29: 7d 07 jge 32 <bubble_p+0x32>
0x0000: | 2b: 89 5c 82 04 mov %ebx,0x4(%edx,%eax,4)
0x0000: | 2f: 89 0c 82 mov %ecx,(%edx,%eax,4)
0x0000: | 32: 83 c0 01 add $0x1,%eax
0x0000: | 35: 39 f0 cmp %esi,%eax
0x0000: | 37: 7c e7 jl 20 <bubble_p+0x20>
0x0000: | 39: 83 ee 01 sub $0x1,%esi
0x0000: | 3c: 75 da jne 18 <bubble_p+0x18>
0x0000: | 3e: 5b pop %ebx
0x0000: | 3f: 5e pop %esi
|
0x0000: | Disassembly of section .text.startup:
|
0x0000: | 00000000 <main>:
0x0000: | 0: 31 c0 xor %eax,%eax
|
|
任务三:
基于socket 使用教材的csapp.h csapp.c,实现daytime(13)服务器(端口我们使用13+后三位学号)和客户端
服务器响应消息格式是
“
客户端IP:XXXX
服务器实现者学号:XXXXXXXX
当前时间: XX:XX:XX
”
上方提交代码
提交一个客户端至少查询三次时间的截图测试截图
提交至少两个客户端查询时间的截图测试截图
- 客户端
#include "time.h"
#include<stdlib.h>
#include<pthread.h>
#include<sys/socket.h>
#include<sys/types.h> //pthread_t , pthread_attr_t and so on.
#include<stdio.h>
#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
#define SOCK_PORT 13224
#define BUFFER_LENGTH 1024
#define MAX_CONN_LIMIT 512 //MAX connection limit
struct sockaddr_in s_addr_client;
static void Data_handle(void * sock_fd); //Only can be seen in the file
int main()
{
int sockfd_server;
int sockfd;
int fd_temp;
struct sockaddr_in s_addr_in;
int client_length;
sockfd_server = socket(AF_INET,SOCK_STREAM,0); //ipv4,TCP
assert(sockfd_server != -1);
//before bind(), set the attr of structure sockaddr.
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 sockaddr *)(&s_addr_in),sizeof(s_addr_in));
if(fd_temp == -1)
{
fprintf(stderr,"bind error!
");
exit(1);
}
fd_temp = listen(sockfd_server,MAX_CONN_LIMIT);
if(fd_temp == -1)
{
fprintf(stderr,"listen error!
");
exit(1);
}
while(1)
{
printf("waiting for new connection...
");
pthread_t thread_id;
client_length = sizeof(s_addr_client);
//Block here. Until server accpets a new connection.
sockfd = accept(sockfd_server,(struct sockaddr *)(&s_addr_client),(socklen_t *)(&client_length));
if(sockfd == -1)
{
fprintf(stderr,"Accept error!
");
continue; //ignore current socket ,continue while loop.
}
printf("A new connection occurs!
");
pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd));
}
//Clear
int ret = shutdown(sockfd_server,SHUT_WR); //shut down the all or part of a full-duplex connection.
assert(ret != -1);
printf("Server shuts down
");
return 0;
}
static void Data_handle(void * sock_fd)
{
int fd = *((int *)sock_fd);
int i_recvBytes;
char data_recv[BUFFER_LENGTH];
char ip[20];
//char * data_send = "Server has received your request!
";
char data_send[100];
strcat(data_send,inet_ntoa(s_addr_client.sin_addr));
// puts(s_addr_client.sin_addr)
strcat(data_send,"
20155308
");
while(1)
{
printf("waiting for request...
");
//Reset data.
memset(data_recv,0,BUFFER_LENGTH);
i_recvBytes = read(fd,data_recv,BUFFER_LENGTH);
if(i_recvBytes == 0)
{
printf("Maybe the client has closed
");
break;
}
if(i_recvBytes == -1)
{
fprintf(stderr,"read error!
");
break;
}
if(strcmp(data_recv,"quit")==0)
{
printf("Quit command!
");
break; //Break the while loop.
}
printf("read from client : %s
",data_recv);
if(write(fd,data_send,strlen(data_send)) == -1)
{
break;
}
time_t timep;
time (&timep);
if(write(fd,ctime(&timep),strlen(ctime(&timep))) == -1)
{
break;
}
}
//Clear
printf("terminating current client_connection...
");
close(fd); //close a file descriptor.
pthread_exit(NULL); //terminate calling thread!
}
- 客户端
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/types.h> //pthread_t , pthread_attr_t and so on.
#include<stdio.h>
#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
#define SOCK_PORT 13224
#define BUFFER_LENGTH 1024
int main()
{
int sockfd;
int tempfd;
struct sockaddr_in s_addr_in;
char data_send[BUFFER_LENGTH];
char data_recv[BUFFER_LENGTH];
memset(data_send,0,BUFFER_LENGTH);
memset(data_recv,0,BUFFER_LENGTH);
sockfd = socket(AF_INET,SOCK_STREAM,0); //ipv4,TCP
if(sockfd == -1)
{
fprintf(stderr,"socket error!
");
exit(1);
}
//before func connect, set the attr of structure sockaddr.
memset(&s_addr_in,0,sizeof(s_addr_in));
s_addr_in.sin_addr.s_addr = inet_addr("127.0.0.1"); //trans char * to in_addr_t
s_addr_in.sin_family = AF_INET;
s_addr_in.sin_port = htons(SOCK_PORT);
tempfd = connect(sockfd,(struct sockaddr *)(&s_addr_in),sizeof(s_addr_in));
if(tempfd == -1)
{
fprintf(stderr,"Connect error!
");
exit(1);
}
while(1)
{
printf("Please input something you wanna say(input "quit" to quit):
");
gets(data_send);
//scanf("%[^
]",data_send); //or you can also use this
tempfd = write(sockfd,data_send,BUFFER_LENGTH);
if(tempfd == -1)
{
fprintf(stderr,"write error
");
exit(0);
}
if(strcmp(data_send,"quit") == 0) //quit,write the quit request and shutdown client
{
break;
}
else
{
tempfd = read(sockfd,data_recv,BUFFER_LENGTH);
assert(tempfd != -1);
printf("%s
",data_recv);
memset(data_send,0,BUFFER_LENGTH);
memset(data_recv,0,BUFFER_LENGTH);
}
}
int ret = shutdown(sockfd,SHUT_WR); //or you can use func close()--<unistd.h> to close the fd
assert(ret != -1);
return 0;
}
- 运行结果:
课下作业
课下作业1
- 完成家庭作业4.47,4.48,4.49
- 相应代码反汇编成X86-64汇编
- 把上述X86-64汇编翻译成Y86汇编,并给出相应机器码
发操作过程、测试、问题解决过程博客链接
- 4.47
void bubble(int *data,int c)
{
int i,j;
int *p,*q;
for(i=c-1;i!=0;i--){
p=data;
q=data+1;
for(j=0;j!=i;++j)
{
if(*p>*q)
{
int t=*p;
*p=*q;
*q=t;
}
p++;
q++;
}
}
}
y86
movl $8, %ecx
pushl %ecx #count = 8
movl data, %ecx
pushl %ecx #push data call bubble halt
bubble:
pushl %ebp movl %esp, %ebp
pushl %esi
pushl %ebx
pushl %edx
movl 8(%ebp), %edx #edx == data movl 12(%ebp), %esi #esi == count andl %esi, %esi
je
bubbleEnd #count==0 movl $1, %eax
subl %eax, %esi #count-- je bubbleEnd #count==1
OuterLoop:
movl %edx, %ecx # p = data (ecx) pushl %esi# to save one reg
InnerLoop:
movl (%ecx), %eax
movl 4(%ecx), %ebx
subl %eax, %ebx
movl 4(%ecx), %ebx jg NoSwap
movl %eax, %ebx #swap, so ebx is greater movl 4(%ecx), %eax
NoSwap:
movl %eax, (%ecx)
movl %ebx, 4(%ecx) movl $4, %eaxaddl %eax, %ecx
movl $1, %eax
subl%eax, %esi jne
InnerLoop
popl %esi
movl $1, %eax
subl %eax, %esi jne
OuterLoop
bubbleEnd:
popl %edx
popl %ebx
popl %esi
movl %ebp, %esp
popl %ebp
ret
这个代码我运行后,出现了这个问题?
这个问题不知道怎么解决?
课下作业2
- 把课上练习3的daytime服务器分别用多进程和多线程实现成并发服务器并测试
- 实验过程
- 多进程:
多进程实现daytime服务器,因此需要用到fork()函数创建进程,而课堂上所实现的daytime服务器每次只是接收一个客户端的请求,这会导致服务器的效率比较低下。因此可以采用多进程并发技术提高服务器的处理效率。
- 服务端
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<errno.h>
#include<errno.h>
#include <time.h>
#define SERV_PORT 13321
int std_err(const char* name)
{
perror(name);
exit(1);
}
int main(void)
{
int sfd, cfd, ret;
int len;
pid_t pid;
socklen_t clie_len;
char buf[BUFSIZ], clibuf[32];
//创建服务器套节字
sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd == -1)
std_err("socket");
//定义地址类型
struct sockaddr_in serv_addr, clie_addr;
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
//绑定服务器的IP、端口;
ret = bind(sfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if(ret == -1)
std_err("bind");
//监听链接服务器的客户数量
ret = listen(sfd, 3);
if(ret == -1)
std_err("listen");
clie_len = sizeof(clie_addr);
while(1)
{
//阻塞等待客户端发起链接请求
cfd = accept(sfd, (struct sockaddr*)&clie_addr, &clie_len);
printf("服务器实现者20155308 ");
printf("客户端IP:%s
",inet_ntoa(clie_addr.sin_addr));
time_t t = time(0);
char tmp[64];
strftime( tmp, sizeof(tmp), "%Y/%m/%d %X %A
", localtime(&t) );
//这里无需打印当前时间,应该是客户端打印当前时间
if(cfd == -1)
std_err("accept");
pid = fork();
if(pid < 0)
std_err("fork:");
else if(pid == 0)
{
close(sfd);
break;
}
else //住进程实现逻辑;1.回收子进程,2,关闭不必要的文件描述父 3,继续等待客户端链接,如果有,则继续创建子进程
{
send(cfd,tmp,strlen(tmp),0);
close(cfd);
}
}
return 0;
}
- 客户端
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<strings.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<sys/wait.h>
#include<signal.h>
#include<errno.h>
#include<pthread.h>
#include <pthread.h>
#define SERV_PORT 13321
#define SERV_IP "127.0.0.1"
#define NUM 3
int std_err(const char* name)
{
perror(name);
exit(1);
}
int main(void)
{
int cfd, ret;
char buf[BUFSIZ];
pid_t pid;
int i;
for(i = 0; i < NUM; i++){
pid = fork();
if(pid == 0)
break;
else if(pid < 0)
std_err("fork");
}
if(pid == 0)
{
cfd = socket(AF_INET, SOCK_STREAM, 0);
if(cfd == -1)
std_err("socket");
struct sockaddr_in clie_addr;
clie_addr.sin_family = AF_INET;
clie_addr.sin_port = htons(SERV_PORT);
ret = inet_pton(AF_INET, SERV_IP, &clie_addr.sin_addr.s_addr);
if(ret != 1)
std_err("inet_pton");
ret = connect(cfd, (struct sockaddr*)&clie_addr, sizeof(clie_addr));
if(ret == -1)
std_err("connect");
char buff[256];
int nRecv=recv(cfd,buff,256,0);
if(nRecv>0)
{
buff[nRecv]=' ';
printf("当前时间:%s
",buff);
}
}
close(cfd);
return 0;
}
- 运行结果
- 多线程:
创建一个新的进程本身开销还是比较大的,因为这样会消耗很多务器端的资源。因此可以采用多线程的方法来实现服务器端。
- 服务端
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<assert.h>
#include<string.h>
#include<unistd.h> :close,write,read
#include<ctype.h>
#include<arpa/inet.h>
#include <time.h>
#define SOCK_PORT 9988
#define BUFFER_LENGTH 1024
#define MAX_CONN_LIMIT 5
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);
//before bind(), set the attr of structure sockaddr.
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!
");
exit(1);
}
fd_temp = listen(sockfd_server,MAX_CONN_LIMIT);
if(fd_temp == -1)
{
fprintf(stderr,"listen error!
");
exit(1);
}
while(1)
{
//printf("waiting for new connection...
");
pthread_t thread_id;
client_length = sizeof(s_addr_client);
//Block here. Until server accpets a new connection.
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
", localtime(&t) );
send(sockfd,tmp,strlen(tmp),0);
close(sockfd); //close a file descriptor.
if(sockfd == -1)
{
fprintf(stderr,"Accept error!
");
continue; //ignore current socket ,continue while loop.
}
if(pthread_create(&thread_id,NULL,(void *)(&Data_handle),(void *)(&sockfd)) == -1)
{
fprintf(stderr,"pthread_create error!
");
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("服务器实现者20155308 ");
printf("客户端IP:%s
",inet_ntoa(s_addr_client.sin_addr));
pthread_exit(NULL); //terminate calling thread!
}
- 服务器
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<sys/wait.h>
#include<signal.h>
#include<errno.h>
#include<pthread.h>
#include <pthread.h>
#define SERV_PORT 13321
#define SERV_IP "127.0.0.1"
#define NUM 3
int std_err(const char* name)
{
perror(name);
exit(1);
}
int main(void)
{
int cfd, ret;
char buf[BUFSIZ];
pid_t pid;
int i;
//创建套节字
cfd = socket(AF_INET, SOCK_STREAM, 0);
if(cfd == -1)
std_err("socket");
//定义IP , 端口
struct sockaddr_in clie_addr;
clie_addr.sin_family = AF_INET;
clie_addr.sin_port = htons(SERV_PORT);
//转换IP 字符串的地址
ret = inet_pton(AF_INET, SERV_IP, &clie_addr.sin_addr.s_addr);
if(ret != 1)
std_err("inet_pton");
//链接服务器
ret = connect(cfd, (struct sockaddr*)&clie_addr, sizeof(clie_addr));
if(ret == -1)
std_err("connect");
char buff[256];
int nRecv=recv(cfd,buff,256,0);
if(nRecv>0)
{
buff[nRecv]=' ';
printf("当前时间:%s
",buff);
}
}
//关闭套节字
close(cfd);
return 0;
}
-
代码中出现的问题
-
问题1
解决过程:记得要加上-lpthread参数,这样编译就可以顺利通过了。lpthread是表示要连接到pthread的库是这里省略的lib,你应该可以找到共享库libpthread.so的。
即
这样就可以编译成功了!
- 问题2
连接不上?不知道为什么?正在解决中。。。。