1. 連接配接百度伺服器
// 1. 連接配接百度的伺服器
BOOL result = [self connectIp:@"220.181.111.188" port:80];
if (!result) {
NSLog(@"連接配接失敗");
return;
}
NSLog(@"連接配接成功");
// 連接配接伺服器
- (BOOL)connectIp:(NSString *)ip port:(int)port {
int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
self.clientSocket = clientSocket;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip.UTF8String);
addr.sin_port = htons(port);
int result = connect(clientSocket, (const struct sockaddr *) &addr, sizeof(addr));
if (result == 0) {
return YES;
} else {
return NO;
}
}
2. 構造請求頭
// 模拟構造Http請求頭
NSString *request = @"GET / HTTP/1.1\r\n"
"Host: www.baidu.com\r\n"
"\r\n";
NSLog(@"%@", request);
3. 通路伺服器,并擷取傳回内容
// 伺服器傳回的響應頭 響應體
NSString *response = [self sendAndRecv:request];
NSLog(@"傳回的資料: %@", response);
// 發送和接收資料
- (NSString *) sendAndRecv:(NSString *)sendMsg {
const char *msg = sendMsg.UTF8String;
ssize_t sendCount = send(self.clientSocket, msg, strlen(msg), 0);
NSLog(@"發送的位元組數 %zd", sendCount);
uint8_t buffer[1024];
NSMutableData *datas = [NSMutableData data];
ssize_t recvCount = recv(self.clientSocket, buffer, sizeof(buffer), 0);
[datas appendBytes:buffer length:recvCount];
while (recvCount != 0) {
recvCount = recv(self.clientSocket, buffer, sizeof(buffer), 0);
NSLog(@"接收的位元組數 %zd", recvCount);
[datas appendBytes:buffer length:recvCount];
}
NSString *recvMsg = [[NSString alloc] initWithData:datas encoding:NSUTF8StringEncoding];
return recvMsg;
}
4. 關閉連接配接,并将網頁顯示在UIWebView中
// 關閉連接配接
close(self.clientSocket);
// 截取響應頭,隻保留響應體, 響應頭結束的辨別 \r\n\r\n
// 找指定字元串所在的範圍,從它之後的第一個位置開始截取字元串
NSRange range = [response rangeOfString:@"\r\n\r\n"];
// 截取響應體
NSString *html = [response substringFromIndex:range.length + range.location];
// baseURL為html依賴的外部檔案所在的位址
[self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.baidu.com"]];
5. 完成第四步之後,傳回的網頁是PC版的
要想使得傳回的網頁是手機版的,需要在添加請求頭時添加"User-Agent"這個請求頭,将第2步的請求頭内容更改為
// 模拟構造Http請求頭
NSString *request = @"GET / HTTP/1.1\r\n"
"Host: www.baidu.com\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\n"
"Connection: keep-alive\r\n"
"\r\n";
NSLog(@"%@", request);
6. 完成代碼
//
// ViewController.m
// 請求百度
//
// Created by mazaiting on 18/1/3.
// Copyright © 2018年 mazaiting. All rights reserved.
//
#import "ViewController.h"
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@property (nonatomic, assign) int clientSocket;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 1. 連接配接百度的伺服器
BOOL result = [self connectIp:@"220.181.111.188" port:80];
if (!result) {
NSLog(@"連接配接失敗");
return;
}
NSLog(@"連接配接成功");
// 模拟構造Http請求頭
NSString *request = @"GET / HTTP/1.1\r\n"
"Host: www.baidu.com\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)\r\n"
"Connection: keep-alive\r\n"
"\r\n";
NSLog(@"%@", request);
// 伺服器傳回的響應頭 響應體
NSString *response = [self sendAndRecv:request];
NSLog(@"傳回的資料: %@", response);
// 關閉連接配接
close(self.clientSocket);
// 截取響應頭,隻保留響應體, 響應頭結束的辨別 \r\n\r\n
// 找指定字元串所在的範圍,從它之後的第一個位置開始截取字元串
NSRange range = [response rangeOfString:@"\r\n\r\n"];
// 截取響應體
NSString *html = [response substringFromIndex:range.length + range.location];
// baseURL為html依賴的外部檔案所在的位址
[self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.baidu.com"]];
}
// 連接配接伺服器
- (BOOL)connectIp:(NSString *)ip port:(int)port {
int clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
self.clientSocket = clientSocket;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip.UTF8String);
addr.sin_port = htons(port);
int result = connect(clientSocket, (const struct sockaddr *) &addr, sizeof(addr));
if (result == 0) {
return YES;
} else {
return NO;
}
}
// 發送和接收資料
- (NSString *) sendAndRecv:(NSString *)sendMsg {
const char *msg = sendMsg.UTF8String;
ssize_t sendCount = send(self.clientSocket, msg, strlen(msg), 0);
NSLog(@"發送的位元組數 %zd", sendCount);
uint8_t buffer[1024];
NSMutableData *datas = [NSMutableData data];
ssize_t recvCount = recv(self.clientSocket, buffer, sizeof(buffer), 0);
[datas appendBytes:buffer length:recvCount];
while (recvCount != 0) {
recvCount = recv(self.clientSocket, buffer, sizeof(buffer), 0);
NSLog(@"接收的位元組數 %zd", recvCount);
[datas appendBytes:buffer length:recvCount];
}
NSString *recvMsg = [[NSString alloc] initWithData:datas encoding:NSUTF8StringEncoding];
return recvMsg;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)prefersStatusBarHidden{
return YES;
}
@end