万恶的网络服务器的项目做完了,昨晚调试好程序之后,感觉自己又老了一大截,就像阿科一直说的那样,IT男伤不起啊。
本次项目是网络终端管理系统,程序代码不多,就是网络协议,线程等把人都快搞疯了。项目很简单,做一个网络服务器,有服务端和客户端,客户端连接上服务器之后,能够注册登录,多客户端连接,有心跳机制,有配置文件,客户端发送shell命令能够在客户端显示,客户端有聊天功能,类似QQ,所有日志文件和聊天信息均保存。 这次项目没有规划好时间,起初很快就把基本的框架和注册登录写好了,后来几天没有做多少东西,一直以为时间还多,等到最后真的是不够了哇。昨天还和理武兄去上海植物园逛了一圈。回来继续写代码,一直到凌晨两点。 第一个问题是shell 命令,起初shell命令写好了,重定向到客户端屏幕显示正常,输入ls的时候可以用,但是pstree –p的时候就不行了,经检查后当发现逻辑有一定问题,缓存空间太小,必须循环读取数据。后来虽然是能够循环读写了,但是忘记加结束符’\0’,命令显示也不正常。 第二个问题是心跳机制,所谓心跳机制就是客户端连接服务器之后,隔一段时间向服务器发送一个信号,表示该用户在线,当用户意外退出或者无操作时,服务器端的心跳处理函数开始处理,定时器时间到了就会把客户端用户置为不在线状态。我想了一个很简单的办法,在用户链表里面设了一个heart,注册时置-1,正常退出置-1,在客户端用alarm函数,循环向服务器发信号,如果服务器收到信号,就将heart置为10,服务器心跳处理函数就是当heart为10时,用户在线正常,当heart>0时,heart减1,heart=0时用户离线成功。服务器也是用alarm函数循环处理心跳。 第三个问题是线程,起初客户端只开了两个线程,其中一个线程只处理聊天信息,但是在退出聊天的时候,无法正常退出。当时我在想,主线程和子线程应该是同时读取服务器发来的信号,后来经过我很多次的实验,发现在子线程发给服务器的信号,只有子线程能接收到,这样我就想了一个办法,先结束子线程,再用pthread_join回收子线程资源,然后在主线程发送一个信号给服务器,这样主线程就能读取到服务器的信号了。后来我用了三个线程,两级菜单两个线程,处理聊天信息一个线程,其中一个我用了return结束子线程,还有一个用了pthread_exit结束子线程,都成功了。不知道我的想法对不对。 pthread_join的作用:使一个线程等待另一个线程结束。代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,从而使创建的线程没有机会开始执行就结束了。加入pthread_join后,主线程会一直等待直到等待的线程结束自己才结束,使创建的线程有机会执行。 第四个问题是保存和读取文件的问题。以前做项目都是保存二进制文件,这次保存日志文件和读取配置文件。经百度之后知道了操作文本文件的办法。保存代码: printf(fd,”%s”,buf); printf(fd,”%d”,i); fprintf用法和printf用法一样,多了一个文件描述符。 读取代码如下: FILE *fp; fp = fopen(“./ip”,”r”); while(!feof(fp)) ipbuf[i++]=getc(fp); ipbuf[i-2]= ‘\0’; fopen第一个参数是文件路径。ipbuf里面存放的就是ip文件的数据。 第五个问题是获取系统时间,保存日志文件时,保存项目有ip、用户、操作、操作时间。操作时间就是系统时间咯,代码如下: #include<time.h> #include<stdio.h> char *buf = NULL; time_t now; struct tm *timenow; time(&now); timenow=localtime(&now); printf("time : %s\n",asctime(timenow)); buf = asctime(timenow); printf("buf:%s\n",buf); 第六点就是字节序对齐问题。到现在还不是很理解,需要在再深入理解一下。 软件运行暂时能够实现项目的要求。这次没做好的很重要的一点就是,没有时间写代码注释了,代码存放得相当乱,因为修改了很多次,宏定义和函数名、变量名等取名很垃圾。网络数据包传送的无用东西太多,为了图方便,所有信息全部存在了数据包里面,占用了大量的网络资源。还有一个重要的问题是线程没有做同步浪费了内核资源。
|