用I/O完成端口+socket编写客户端demo实现Http下载

//暂时先把已完成的部分记录下来,这个demo先暂停下来,这个还没有实现好的。
最近学习了一些网络编程的知识,想要在vs2015下实现一个控制台应用程序,通过命令行启动,
启动方式:client url download_path
可以从指定的下载地址把文件下载到本地指定的路径。


socket下载流程:
1.初始化winscok库。
2.解析url,根据url规范,一个url地址长这样:(协议名://)+(主机名)+(:端口号)+(//页面地址)。
此处需要拿到主机名。
3.通过主机名可以获取ip地址,有两种方法,一是通过api获取,可以通过gethostbyname获取,但是这个api已经被弃用了,如果要使用要在vs项目属性->C/C++->预处理器定义 增加_WINSOCK_DEPRECATED_NO_WARNINGS。msdn的建议是使用getaddrinfo这个api,试了一下,会得到一个结构,还没完全理解清楚,就没有用(待再次尝试)。
二是可以通过dns解析,然后获取,就是像在命令行那里敲ping+主机名那样,也可以得到的,但是这个具体原理我还没完全搞清楚,尝试了一下失败了(待再次尝试)。
4.拿到ip地址之后,http协议默认端口号80。
然后就可以建立连接了,有两种方式:(阻塞)connect,(非阻塞)ConnectEx。此处使用异步的ConnectEx,需要使用到重叠结构。注意ConnectEx不能像connect那样直接调用的,是要通过函数指针LPFN_CONNECTEX来使用的。
5.与服务器建立好连接之后,需要向服务器发送一个请求,这里打算使用异步的WSAsend()
6.发送请求之后可能是立即返回的(之前好像看到说是返回的一般都是失败的,因为他还没完成),这块还没了解清楚,之后用WSARecv()收回应。这个时候要解析他回应的消息,要划分消息头和消息体。消息头的特征是末尾是\r\n,而消息体是\r\n\r\n。可以遍历获取到的回应然后划分开。
7.确定消息体的长度。
8.消息体就是要拿的数据,然后要看看数据是不是压缩过的呀,如果是有content-encoding这个属性的话它就是被压缩过的,那么就需要解压数据。这个属性好像是在请求头可以看到(待…),这块还没了解清楚。
9.拿到了数据之后,就保存到本地,这里是打算直接写入到本地的文件里。写入之前应该判断一下本地是否存在这个文件,存在就删掉写入,不存在就直接创建然后写入。


I/O完成端口流程:
1.创建I/O完成端口。
2.创建下载要用的那个socket,然后把他和已经创建好的完成端口绑定起来。
3.分别创建读和写的重叠结构。
4.创建工作者线程。这个线程是完成整个下载的逻辑的。里面是一个循环,处理包括收发数据的逻辑,它是一直进行的,直到收到退出消息。
5.当完成了下载之后,就在队列里面投递一个完成封包,然后就告诉线程,完成啦你来处理数据吧!但是因为是异步的所以会立即返回(好像是这样),这时要判断是不是pending,就是它是不是还没完成呀,没完成就做完了再处理!这里好像是可以设置一个超时把,如果超时了就不干啦!想设置成要是超过10分钟没有下载速度的话就取消下载。
6.处理完数据之后释放资源。卸载库。


参考:
基于TCP的Socket 编程
完成端口详解
IOCP模型与网络编程
Windows环境下用C++实现socket编程
IOCP浅析与实例
比较两种设计模式:reactor和proactor
(参考这篇文章是因为之前不知道在哪里看到说windows的完成端口其实就是proactor的实现,所以就看了这个)
C++ new的nothrow关键字和new_handler用法
(这个是一个细节的问题,所以也想把这篇文章链接贴出来方便以后查阅)

你可能感兴趣的:(网络编程,c++)