简单讲述基于BSD Socket + Http 协议。打造自己的浏览器。
BSD Socket,不多说的,有机会详细参考网上有很多详细的讲解的。
本例通过组一个Http报文,发送到指定的服务器中,得到相应的返回值。本人使用的是www.baidu.com,作为试验。
1。
下载fiddler,安装。这是一个抓报工具。安装结束,打开fiddler2,打开浏览器。把尽可能访问网络的东西关掉。晴空fiddler2里面纪录,然后浏览器地址栏输入www.baidu.com,进入,之后搜索一个关键字,例如,alexliu,然后看包是如何发送的。 发现使用的是GET方法,关键字通过编码方式转换,然后有如下请求。
is :GET http://www.baidu.com/s?wd=alexliu HTTP/1.1
Host:www.baidu.com
于是自行组一个Header。记得末尾有两个回车换行。“/r/n"
2。
域名解析成IP地址。
struct hostent *host = gethostbyname([theHost UTF8String]);
if(!host)
{
herror("resolv");
return NULL;
}
struct in_addr **list = (struct in_addr **)host->h_addr_list;
NSString *address = [NSString stringWithCString:inet_ntoa(*list[0])];
return address;
3。
通过Socket系统提供的接口,进行发送和接受。
their_addr.sin_family = AF_INET;
their_addr.sin_addr.s_addr = inet_addr(/* 自己解析IP去吧*/);
//80端口
their_addr.sin_port = htons(80);
bzero(&(their_addr.sin_zero), 8);
int conn = connect(sockfd, (struct sockaddr*)&their_addr, sizeof(struct sockaddr));
//连接
if(conn != -1)
{
NSLog(@"Then the conn is not -1!");
NSMutableString* httpContent = [self makeHttpHeader:hostName];
//这个地方Data需要自己把HTTP那个Header进行加工。
ssize_t dataSended = send(sockfd, [data bytes], [data length], 0);
// readBuffer 大小自行定义。
int br = 0;
//receive 需要一直取到定义的大小为止,循环部分按需要的加
br = recv(sockfd, readBuffer, sizeof(readBuffer), 0);
}
4。显示。顺便上2个小图。
首先输入搜索需求
搜索结果太多了,可以滚动,但是返回的仍然是很多乱七八糟的。。要是有个IEDeveloper 或者fireDebug之类的东西就好了。我这个只能显示纯文本。。
5。有了回来的HTTP+XML文件
自行使用好用的Parser 之类的解析,然后再来点控件,显示到控件上面。浏览器就能面世了。。:)
由于iPhone的SDK 里面提供的接口是CF Socket。简单DEMO下。
一点基础补充:
Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序。要学Internet上的TCP/IP网络编程,必须理解Socket接口。
Socket接口设计者最先是将接口放在Unix操作系统里面的。如果了解Unix系统的输入和输出的话,就很容易了解Socket了。网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。
// 定义读写的 stream.
CFReadStreamRef myReadStream = NULL;
CFReadStreamRef myWriteStream = NULL;
//Socket的建立 下面有参数的原始声明
///* This is a synonym for NULL, if you'd rather use a named constant. */
//CF_EXPORT
//const CFAllocatorRef kCFAllocatorDefault;
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault,
/*host*/ ,
/*端口*/,
&myReadStream,
&myWriteStream);
// 打开Stream.
if (myReadStream != NULL && CFReadStreamOpen(myReadStream))
{
UInt8 readBuffer[10];
while (CFReadStreamHasBytesAvailable(stream))
{
//进行读操作
CFReadStreamRead(stream, buffer, 10);
}
}
// 写操作
if (myWriteStream != NULL && CFWriteStreamOpen(myWriteStream))
{
// 写一个byte.
UInt8 writeBuffer[1];
writeBuffer[0] = 42;
CFWriteStreamWrite(stream, writeBuffer, 1);
}
//关闭Stream
CFReadStreamClose(myReadStream);
CFWriteStreamClose(myWriteStream);
//Release掉不需要的资源
CFRelease(myReadStream);
CFRelease(myWriteStream);