第8周课堂测试3(课上未完成)
课上练习3:基于socket 使用教材的csapp.h csapp.c,实现daytime(13)服务器(端口我们使用13+后三位学号)和客户端
服务器响应消息格式是
“客户端IP:XXXX
服务器实现者学号:XXXXXXXX
当前时间: XX:XX:XX”
实现daytime服务器和客户端:
完成这个作业首先要复习并仔细阅读第11章,针对11章里的示例代码,写了一篇博客分析每句代码和函数。第11章代码详解
参考书上P662,echo客户端和服务器的示例,编译书上的示例就遇到一堆问题。
- 需要先从网上下载随书源代码,将csapp.h头文件复制到工作目录下,但这样仍然无法在main函数中找到相关函数定义。
- 将csapp.c文件复制到工作目录下,因为csapp.h头文件中的函数定义具体实现是在csapp.c中的,然后通过分步编译得到csapp.o 和 serveri.o,再进行链接。
- csapp.c里包含pthread多线程编程的一些函数,在编译时,需要加上参数“-pthread”。
- 服务器和客户端都编译完成后,得到两个server、client两个可执行文件,但一运行就连接失败。
- 仔细看Open_clientfd这个函数,发现因为是csapp.c用的是第二版书的代码,所以在定义端口时,csapp.c中用的int型,而第三版书上echoserveri.c中端口用的字符串。导致连接不成功。
解决办法:用atoi函数将传入的字符串参数转为int型参数,再传入Open_clientfd函数。
- 修改后再运行又出现客户端拒绝访问(permission denied)
解决办法:用sudo命令运行客户端,成功运行。
- 再打开客户端,瞬间成功连接上服务器。不断从客户端输入文本,并发送到服务器,服务器读取并回送,再从客户端标准输出。
然后,基于这个示例,我们只需修改服务器功能,让服务器按格式返回时间即可。
用老师教的man -K大法
man 2 -K time
但time函数得到的系统时间是秒数,需要转换一下格式。
time函数的SEE ALSO里给我们提示,继续用man -K搜索gmtime
gmtime是一个指针函数,返回一个指向struct tm结构体类型的指针。
修改服务器echo函数:
void echo(int connfd, char *haddrp)//客户端IP
{
time_t t;
struct tm * lt;
size_t n;
char buf[MAXLINE];
rio_t rio;
Rio_readinitb(&rio, connfd);
while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
printf("\n客户端IP:%s\n",haddrp);
printf("服务器实现者学号:20155225\n");
time (&t);
lt = gmtime (&t);
printf ("当前时间为:%d/%d/%d %d:%d:%d\n",lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec);
//Rio_writen(connfd, buf, n);
}
}
编译过程中仍然存在问题,修改echo函数后,对eho函数说明和引用都需要修改参数。
最后成功实现了time服务器和客户端,如下图所示。