iOS 使用Socket模拟手机访问百度

简介: 1. 连接百度服务器 // 1. 连接百度的服务器 BOOL result = [self connectIp:@"220.181.111.

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
目录
相关文章
|
3月前
|
语音技术 开发工具 图形学
Unity与IOS⭐一、百度语音IOS版Demo调试方法
Unity与IOS⭐一、百度语音IOS版Demo调试方法
|
27天前
|
安全 搜索推荐 Android开发
Android vs. iOS:解锁智能手机操作系统的奥秘####
【10月更文挑战第21天】 在当今这个数字化时代,智能手机已成为我们生活中不可或缺的伙伴。本文旨在深入浅出地探讨两大主流操作系统——Android与iOS的核心差异、优势及未来趋势,帮助读者更好地理解这两个平台背后的技术哲学和用户体验设计。通过对比分析,揭示它们如何塑造了我们的数字生活方式,并展望未来可能的发展路径。无论您是技术爱好者还是普通用户,这篇文章都将带您走进一个充满创新与可能性的移动世界。 ####
47 3
|
30天前
|
Android开发 iOS开发 UED
安卓与iOS的较量:谁才是智能手机市场的王者?
本文将深入探讨安卓和iOS两大智能手机操作系统之间的竞争关系,分析它们各自的优势和劣势。通过对比两者在市场份额、用户体验、应用生态等方面的表现,我们将揭示出谁才是真正的市场领导者。无论你是安卓粉丝还是iOS忠实用户,这篇文章都将为你提供一些有趣的观点和见解。
|
3月前
|
XML 安全 Android开发
Flutter配置Android和IOS允许http访问
Flutter配置Android和IOS允许http访问
122 3
|
3月前
|
语音技术 开发工具 图形学
Unity与IOS⭐二、Unity接入IOS版百度语音:语音唤醒
Unity与IOS⭐二、Unity接入IOS版百度语音:语音唤醒
Unity与IOS⭐二、Unity接入IOS版百度语音:语音唤醒
|
3月前
|
开发工具 iOS开发 容器
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
|
4月前
|
存储 移动开发 Android开发
使用kotlin Jetpack Compose框架开发安卓app, webview中h5如何访问手机存储上传文件
在Kotlin和Jetpack Compose中,集成WebView以支持HTML5页面访问手机存储及上传音频文件涉及关键步骤:1) 添加`READ_EXTERNAL_STORAGE`和`WRITE_EXTERNAL_STORAGE`权限,考虑Android 11的分区存储;2) 配置WebView允许JavaScript和文件访问,启用`javaScriptEnabled`、`allowFileAccess`等设置;3) HTML5页面使用`<input type="file">`让用户选择文件,利用File API;
|
4月前
|
人工智能 搜索推荐 vr&ar
苹果手机iOS18最新升级:植入AI人工智能,国内百度文心一言,国外GPT4o来辅助
iOS 18亮点速览:AI强化的Siri、RCS安卓消息兼容、自定义主屏、辅助功能增强,VR进步,新隐私工具,包括锁定APP和眼动追踪。Passwords app保障安全,Apple Intelligence提升个性化体验。
214 1
|
4月前
|
开发工具 iOS开发 容器
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
iOS Objective-C 应用连接Azure Storage时,若不关闭账号的匿名访问,程序能正常运行。但关闭匿名访问后,上传到容器时会出现错误:“Public access is not permitted”。解决方法是将创建容器时的公共访问类型从`AZSContainerPublicAccessTypeContainer`改为`AZSContainerPublicAccessTypeOff`,以确保通过授权请求访问。
【Azure Blob】关闭Blob 匿名访问,iOS Objective-C SDK连接Storage Account报错
|
5月前
Discuz 手机版访问自动跳转到手机域名
Discuz 手机版访问自动跳转到手机域名
95 1