最近在公司里面写了一个HttpServer的工具,主要是想将路由器的资料在本地浏览,不用每次都要 编译下载到开发板上。
在编写的过程中主要遇到以下的一些问题:
第一:功能规划
工具中有三个功能,字符提取,HttpServer,和比较文件。刚开始时没有想到功能的扩展,导致一些函数没有写成公用函数,提供独立的功能,如请求文件路径的分析。
第二:线程的设计
server运行后需要等待用户连接,所以需要写成无限循环等待,这样就要用到线程的方法。
第三:非阻塞的处理
服务器需要等待用户的链接,不能够让线程阻塞,这样界面线程将获取不到运行时间,导致不可访问。
第四:FRAME的处理,因为需要同一个请求项发出多个请求,每个请求返回到不同的target中,这样可以同时访问两套资源文件。
以下记录一些使用的方法和调试的方 法:
1.线程的创建
我使用的是
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes
DWORD dwStackSize, // initial thread stack size
LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function
LPVOID lpParameter, // argument for new thread
DWORD dwCreationFlags, // creation flags
LPDWORD lpThreadId // pointer to receive thread ID
);
这个函数主要注意的是两个参数,线程函数指针和传给线程函数指针的参数。
创建线程:hThread = CreateThread(NULL,0,DownloadWebCode,this,0,NULL);我是将整个窗口类的指针传进线程函数中,这样线程函数就可以访问窗口类的成员变量和函数。
线程函数的声明:
static unsigned long __stdcall Function(void param);
然后函数的定义:
unsigned long CWebSiteToolDlg::DownloadWebCode(void *pPara)
在线程函数中需要将变量做类型转换:
CWebSiteToolDlg *param ;
param = (CWebSiteToolDlg *)pPara;
非阻塞套接字:
因为服务器启动后需要等待用户连接,而线程又不能阻塞,这里我用到io复用。用的是select函数监听套接字。
select函数原型如下:
int select (
int nfds,
fd_set FAR * readfds,
fd_set FAR * writefds,
fd_set FAR * exceptfds,
const struct timeval FAR * timeout
);
这里要注意监听的套接字集合的顺序,显示读集合,然后是写集合,异常集合一帮不用,最好的是时间,就是在多长的时间内对套接字结合进行监听。
select模式用到的宏
FD_CLR(s, *set)
Http服务器的处理流程
1.获取本地的主机名
使用函数gethostname函数
2获取本地IP
使用函数gethostbyname
然后绑定本地主机,创建套接字,绑定套接字,将套接字加入要监听的结合中。
然后 select监听,判断监听的套接字是否在读结合中,如果是,就accept,然后用返回的套接字进行通信。
但出现一个问题,就是在运行软件 客户端已经发出了请求获取本地资源的命令,但是运行时用AfxMessageBox打出请求命令是发现是空,导致文件获取不到。调试时没有这个问题,在accept后用sleep()函数休眠该问题解决。
用FRAME浏览多个页面。
这个问题还没有解决。我的设想是这样的:点击一个菜单,两个FRAME里面分别读取不同文件夹下的资源文件。
但是问题存在:第一,点击一个菜单发出的请求命令是一样的,所以要发出两次链接请求,但是两次的请求返回的到的Frame是不一样的,第一请求返回的FRAME的target是骄傲frame1,第二个是frame2。我是用<a>的onClick函数实现的,
如下:
obj.href = url;1
obj.target = frame1;
obj.href = url2;
obj.target = frame2;
但是发现返回的文件只是到frame2中。
尝试用 settimeout()函数让第二次的href 延时2秒,还是没有成功。这个问题明天调试。
以上都是我在做过程中的一些问题和解决方法,如果知道问题原因的请跟帖。