[New learn] 网络基础-网络操作
代码:https://github.com/xufeng79x/NETOperation
1.简介
主要记录基本的网络操作步骤,get/post关系和区别和文件上传实现。
2.准备
需要服务器端,如果你没有完成服务器端的操作请参考[New learn] 网络基础-apache本地服务搭建(支持php)
3.网络基本操作
3.1.基本操作步骤
//step_1:创建URL
//step_2:创建request
//step_3:建立连接接受返回数据
//step_4:反序列化数据
举例:如下我们将按照此步骤从网络上下载图片显示在UI上。
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self downloadFile];
}
-(void)downloadFile
{
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperationWithBlock:^{
//step_1:创建URL
NSString *urlStr = @"http://imgsrc.baidu.com/forum/pic/item/645b8701a18b87d6e716e197070828381e30fdae.jpg";
NSURL *url = [NSURL URLWithString:urlStr];
//step_2:创建request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy: timeoutInterval:2.0f];
//step_3:建立连接接受返回数据
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// step_4:反序列化数据
UIImage *image = [[UIImage alloc]initWithData:data];
// 设定UI显示
self.imageView.image = image;
}];
}];
}
结果:

说明:这里只是快速演示了一个网络请求的过程,无论后续讲到的get、post该是文件上传等都不脱离这个大的过程,无非是细节的不同罢了。
3.2 网络操作过程原理
一般网络请求方式分为多种,但是我们最常用的只有GET和POST两种(默认为GET),这两者的区别和使用场景及原理本文后续会涉及。
客户端与服务端的通信原理如下图:

上图中,GET操作是没有请求体的,那的所有参数都放在了URL(请求行)中,而对于POST操作则没有URL参数这个说法而是将所有的参数(包括文件的二进制内容)都放在请求体中。
GET
例如我们访问:http://127.0.0.1/login 在GET 请求演示中输入正确的用户名和密码:xf/ios

点击URL后在地址栏中出现了我们输入的内容:

请求行与请求头:

上述红框中的为请求行,它指明了协议,方式(GET)和URL。其余部分为请求头
对于相应部分可以自行测试观察。
总结:我们可以看到GET方式它的参数都是在URL中显式指定的,对于用户名和密码这个场景来说显然就不适合了。这样的场景下我们可以POST方式更为妥当。
POST
例如我们访问:http://127.0.0.1/login 在POST 请求演示中输入正确的用户名和密码:xf/ios

点击URL后在地址栏中并没有出现用户名和密码:

请求行与请求头:

上述红框中的为请求行,它指明了协议,方式(GET)和URL。其余部分为请求头
对于相应部分可以自行测试观察。
请求体:
总结:我们可以看到POST方式指定的,用户名和密码不会出现在URL中,然是被包装进了请求体中,同时这些用户信息也不会被服务器端的日志所记录。
3.3 网络操作过程代码实现
进过上述过程已经对网络的原理有了简单地认识,并且我们也通过浏览器进行了两种方式的操作,而使用代码来实现无非是借助于框架的API来模拟还原这个过程。
GET
代码:
- (void)getLogin
{
// step_1:创建URL
NSString *username = @"xf";
NSString *pwd = @"ios";
NSString *urlString = [NSString stringWithFormat:@"http://127.0.0.1/login.php?username=%@&password=%@",username, pwd];
NSURL *url = [NSURL URLWithString:urlString];
// step_2:创建request
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy: timeoutInterval:2.0f];
// step_3:建立连接接受返回数据
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// 反序列化
id result = [NSJSONSerialization JSONObjectWithData:data options: error:NULL];
NSLog(@"%@", result);
}];
}
结果:可以看到与浏览器返回的数据是一致的。
-- :::] {
userId = ;
userName = xufeng;
}
总结:GET操作的时候无非就是去将参数拼接进URL,通过这个URL去获取数据
POST
代码:
- (void)postLogin
{
// step_1:创建URL
NSString *urlString = @"http://127.0.0.1/login.php";
NSURL *url = [NSURL URLWithString:urlString];
// step_2:创建request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy: timeoutInterval:2.0f];
// 2.1 指定http的访问方法,服务器短才知道如何访问
request.HTTPMethod = @"POST";
// 2.2 指定数据体,数据体的内容可以从firebug里面直接拷贝
NSString *username = @"xf";
NSString *pwd = @"ios";
NSString *bobyStr = [NSString stringWithFormat:@"username=%@&password=%@", username, pwd];
// 2.2.1 跟服务器的交互,全部传递的二进制
request.HTTPBody = [bobyStr dataUsingEncoding:NSUTF8StringEncoding];
// step_3:建立连接接受返回数据
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// 反序列化
id result = [NSJSONSerialization JSONObjectWithData:data options: error:NULL];
NSLog(@"%@", result);
}];
}
结果:可以看到与浏览器返回的数据是一致的。
-- :::] {
userId = ;
userName = xufeng;
}
总结:与GET不同的是
1)使用NSMutableURLRequest类来申明请求,因为后续需要设置此request。
2)需要显式的设定reguest为POST
3)参数不会拼接到URL而是使用以二进制数据的形式设定到request的请求体中。
4.网络高级操作--文件上传
前提:保证服务器端目标文件夹为可读写。
与之前过程一样,我们先进行浏览器的操作然后在使用代码来模拟实现。
打开http://127.0.0.1/post/upload.html

选择文件上传并观察网络请求:
我们可以看到文件已经被成功上传到服务器:
对应的请求行和请求行如下:
POST /post/upload.php HTTP/1.1 Host: 127.0.0.1 Connection: keep-alive Content-Length: Cache-Control: max-age= Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Origin: http://127.0.0.1 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.80 Safari/537.36 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryOKUHB11qxaAPiisz Referer: http://127.0.0.1/post/upload.html Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8
请求体:

我们现在了解了上传是基于POST方式,按照之前的操作我们需要在代码中来模拟实现。
而在操作步骤中唯一不同的就是对于request的包装,所以上传文件部分给NSMutableURLRequest增加一个分类来生成请求。
代码实现:
#import "NSMutableURLRequest+Multipart.h"
/**随便的字符串作为分隔符*/
static NSString *boundary = @"xufeng-test";
@implementation NSMutableURLRequest (Multipart)
+ (instancetype)requestWithURL:(NSURL *)url andLoaclFilePath:(NSString *)loaclFilePath andFileName:(NSString *)fileName
{
//step_2:创建request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy: timeoutInterval:2.0f];
// 2.1 指定post方法
request.HTTPMethod = @"POST";
// 2.2 拼接数据体
NSMutableData *dataM = [NSMutableData data];
NSString *str = [NSString stringWithFormat:@"\r\n--%@\r\n", boundary];
[dataM appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
str = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"%@\" \r\n", fileName];
[dataM appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
// 这里直接指定为octet-stream,这样可以针对全部的文件格式
str = @"Content-Type: application/octet-stream\r\n\r\n";
[dataM appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
// 要上传图片的二进制
[dataM appendData:[NSData dataWithContentsOfFile:loaclFilePath]];
str = [NSString stringWithFormat:@"\r\n--%@--\r\n", boundary];
[dataM appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
// 2.3 设置请求体
request.HTTPBody = dataM;
// 2.4 设置请求头
NSString *headerStr = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:headerStr forHTTPHeaderField:@"Content-Type"];
return request;
}
调用:
- (void)postUpLoadFile {
// 1. 创建URL
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/post/upload.php"];
// 2. 创建request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url andLoaclFilePath:[[NSBundle mainBundle] pathForResource:@"test.png" ofType:nil] andFileName:@"test.png"];
// 3. 建立连接接受返回数据
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// 4. 反序列化数据
id result = [NSJSONSerialization JSONObjectWithData:data options: error:NULL];
NSLog(@"result = %@", result);
}];
}
结果:
-- :::] result = {
userfile = {
error = ;
name = "test.png";
size = ;
"tmp_name" = "/private/var/tmp/phpUWTlJ2";
type = "application/octet-stream";
};
}
查看服务器文件夹,已经正确上传:

完毕。
[New learn] 网络基础-网络操作的更多相关文章
- Linux系统学习 五、网络基础—网络通信协议
OSI/ISO七层模型和TCP/IP四层模型 网络层协议和IP划分 OSI的七层框架 物理层:设备之间的比特流的传输.物理接口.电气特性等. 数据链路层:成帧.用MAC地址访问媒介.错误检测与修正. ...
- python-socket编程(入门,网络基础)
一.网络基础 网络建立的目的是为了数据交互(通信) 如何实现通信: 1.建立好底层的物理连接介质 2.有一套统一的通信标准,称之为互联网协议 1.osi七层协议 互联网协议按照功能的不同分为osi七层 ...
- Python服务器开发 -- 网络基础
Python服务器开发 -- 网络基础 网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.HTTP是高层协议,而TCP/IP是个协议集,包过许多的子协议.... 网络由下 ...
- Python服务器开发二:Python网络基础
Python服务器开发二:Python网络基础 网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层. HTTP是高层协议,而TCP/IP是个协议集,包过许多的子协议.包括: ...
- python 网络篇(网络编程)
一.楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运行,你就会发现,这两个python的文件分别运行的很好.但是如果这两个程序之间想要传递一个数据, ...
- 前端学HTTP之网络基础
× 目录 [1]网络 [2]OSI [3]TCP/IP 前面的话 HTTP协议对于前端工程师是非常重要的.我们在浏览网站时,访问的每一个WEB页面都需要使用HTTP协议实现.如果不了解HTTP协议,就 ...
- TCP/IP协议(一)网络基础知识
参考书籍为<图解tcp/ip>-第五版.这篇随笔,主要内容还是TCP/IP所必备的基础知识,包括计算机与网络发展的历史及标准化过程(简述).OSI参考模型.网络概念的本质.网络构建的设备等 ...
- 网络基础:NetBIOS
网络基础小补. 利用 NetBIOS 名称与其他计算机通信 网络中的计算机之间必须知道IP地址后才能相互通信.但对人来说IP难以记忆,NetBIOS计算机名称比较容易记忆.当计算机使用 NetBIOS ...
- JAVA基础知识之网络编程——-网络基础(Java的http get和post请求,多线程下载)
本文主要介绍java.net下为网络编程提供的一些基础包,InetAddress代表一个IP协议对象,可以用来获取IP地址,Host name之类的信息.URL和URLConnect可以用来访问web ...
随机推荐
- [洛谷P2447][SDOI2010]外星千足虫
题目大意:有$n$个数,每个数为$0$或$1$,给你其中一些关系,一个关系形如其中几个数的异或和是多少,问最少知道前几个关系就可以得出每个数是什么,并输出每个数 题解:异或方程组,和高斯消元差不多,就 ...
- POJ3666:Making the Grade——题解
http://poj.org/problem?id=3666 题目大意:给n个数,每次操作可使一个数+1或-1,求最小操作数使得序列不下降或不上升. —————————————————————— 思路 ...
- POJ1204:Word Puzzles——题解
http://poj.org/problem?id=1204 题目大意:给一个字母表,求一些字符串的开端第一次出现的位置和字符串的方向(字符串可以按照八个方向放在字母表中可匹配的位置) ——————— ...
- POJ1201:Intervals(差分约束)
差分约束经典题.设s[i]为前缀和,则有 s[i]-s[i-1]<=1 (i往i-1连-1的边) s[i]>=s[i-1] (i-1往i连0的边) s[b]-s[a-1]>=c (a ...
- X day2
题目 官方题解 T1: 我们可以把问题化简为$a\times b \times c \leq n $中的有序$(a,b,c)$有多少组.分三种情况考虑 当$a=b=c$时,答案十分好统计 当$a< ...
- expect使用小结
因为工作关系,需要经常从线上机器上拉取数据,于是想着能否写个脚本,自动完成这个任务呢? 我一般使用scp在机器间传输文件,然而每次scp都需要输入密码,自动化脚本怎么解决这个问题呢?于是expect这 ...
- svg学习
百度百科: SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言(XML),用于描述二维矢量图形的一种图形格式.SVG是W3C制定的一种新的二维矢量图形格式,也 ...
- 剑指offer --合并链表
题目:输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. 解法://递归解法 public class MixLink { /* public class L ...
- codevs 1332 上白泽慧音
1332 上白泽慧音 时间限制: 1 s 空间限制: 128000 KB 题目描述 Description 在幻想乡,上白泽慧音是以知识渊博闻名的老师.春雪异变导致人间之里的很多道路都被大 ...
- 数据结构:Bitset
这个东西看起来很棒棒的样子呀 bitset存储二进制数位 bitset就像一个bool类型的数组一样 bitset中的每个元素都能单独被访问 整数类型和布尔数组都能转化成bitset 有关Bitset ...