网络编程

软件系统架构两种方式

B / S: Browser / Server (Web浏览器 + Web服务器)

C / S: Client / Server (客户端 + 服务器)

服务器:

FTP服务器(File Transport Protocol)

Web服务器:提供各种网页请求的服务的机器

域名和IP地址的关系(Web浏览器和服务器流程)?

Web浏览器输入域名(发送请求html主页)-> DNS服务器(域名和IP映射)-> IP地址 -> 找到Web服务器 -> 服务器响应(返回请求的主页) -> Web浏览器解析并显示主页(解析html文档,再显示)

样例:把本地的Mac机器变成Web服务器(提供响应html文档服务的机器)

 1. 启动Mac已经支持的Apache软件, 终端执行命令

    sudo apachectl start

2. 验证:浏览器编辑框中输入  localhost

   -》 看到It works!, 启动成功

3. 找到It works对应的html的路径

    /Library/WebServer/Documents/index.html.en

4. 浏览器输入框输入 localhost(本机机器的名字)

    -> 输入 172.60.50.87 (本机的IP地址)

  -> 172.60.50.87/index.html (默认主页一般都是index.html)

  -> 172.60.50.87:80/index.html (默认Web服务器的端口号是80)


端口号port是什么?什么作用?

标识网络应用的逻辑地址;唯一

端口号格式: 1~65535

1 ~ 255被占用:80被Web服务占用;21被FTP服务占用;23被email服务占用

256 ~ 1023被占用:Unix进程占用

1024 ~ 65535:可使用


网络中的三要素:IP地址 + 端口号 + 协议

URL(Uniform Resource Locator:统一资源定位符)

1.作用:找到某台服务器的资源(html主页;图片;音频文件...)

2.格式:协议://域名:端口号/路径/资源名字

http://172.60.50.87:80/index.html

http://172.60.50.87:80/image/test.png

3.常用协议:

a.file协议:本地规定数据传输的协议

file:///Users/lightning111/Library/image/test.png

4.本地URL;还是远程URL

本地URL(NSString -> NSURL):[NSURL fileURLWithString:xxx];

远程URL(NSString -> NSURL):[NSURL urlWithString:@"http://www.baidu.com"];

分析:

1. iPhone模拟器看到的百度主页和Mac浏览器看到的界面不一样

  -> 对移动端又开发一套主页m.baidu.com

  -> 对桌面又开发另一套主页www.baidu.com

2. 响应式编程(Response....): 根据设备不同的分辨率推送不同样式/页面的方式

3. 如果输入https://www.baidu.com,无法显示主页;原因是百度的https和苹果要求的https的证书不太一样


DNS: Domain Name System/Service; 找域名和IP地址关系

[Demo01_UIWebView]

<span style="font-size:14px;">@interface ViewController ()<UIWebViewDelegate>
@property (weak, nonatomic) IBOutlet UIWebView *webView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //1.创建远程NSURL对象;指定请求的url
    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
    //2.创建NSURLRequest对象
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    //2.1 设置代理
    self.webView.delegate = self;
    //3.使用webView对象加载请求
    [self.webView loadRequest:request];
}

//开始加载
- (void)webViewDidStartLoad:(UIWebView *)webView{
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
//成功加载完毕
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
//失败返回
- (void)webView:(UIWebView *)webView didFailLoadWithError:(nullable NSError *)error{
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    NSLog(@"请求百度主页失败:%@", error.userInfo);
}
</span>


UIWebView和WKWebView的区别

UIWebView能做什么?

1. 加载本地/远程HTML文档

2. 导航上一个或者下一个web页面

3. 运行基本/简单的JavaScript


WKWebView能做什么?

1. iOS8引入的控件;WebKit Framework; 完全可以替代UIWebView

2. iOS和Mac两个平台的统一控件

3. 响应速度60fps(Frame Per Second)

4. 占用内存是UIWebView的1/3 ~ 1/4

5. 可以运行较复杂的JavaScript


样例(理解):使用WKWebView加载百度主页

 【Demo02_WKWebView】

1. WKWebView只能用代码创建添加

2. WKNavigationDelegate

<span style="font-size:14px;">- (void)viewDidLoad {
    [super viewDidLoad];
    
    //1.创建NSURL
    NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];
    //2.创建NSURLRequest
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    //3.创建WKWebView对象,添加到界面(storyboard没有控件)
    WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.frame];
    [self.view addSubview:webView];
    //3.1 设置代理
    webView.navigationDelegate = self;
    //4.加载请求
    [webView loadRequest:request];
}

//开始加载
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
//加载成功
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
//加载失败
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
    NSLog(@"百度主页加载失败:%@", error.userInfo);
    
}
</span>



Socket通信是什么?

什么是Socket(插孔/插座)?

两个网络程序通过一个双向的通信连接实现数据交换的过程


如何实现Socket聊天功能(局域网内)?

三个步骤:

1. 服务器处于监听状态(机器开机+软件启动) -> 端口打开

2.客户端发送Socket连接(成功:发送数据通道打开; 失败:无法发送数据)

3.发送数据; 接收数据


网络层(从上到下):

应用层协议:HTTP/HTTPS; FTP; XMPP;

  Socket(接口:发送/接收数据; 连接)

数据传输层协议:TCP/UDP


样例:实现Socket聊天功能(局域网内)

  【Demo03_Socket】

 -> 第三方封装原生的Socket接口

 -> 客户端的界面:

      UITextField: IP; UIButton:连接; UITextField(消息);UIButton(发送消息); UITextView(显示服务器端的消息)

 -> 如何执行发送聊天的功能(步骤)

    1. 一个同学做服务器端,只要启动AsyncSocket-Server工程即可

    2. 另一个同学做客户端,启动Demo03_Socket项目,在界面上输入对方的ip

    3. 点击“连接对方机器”的按钮,直到在终端看到“连接成功!!!!!!!!”为止

    4. 此时双方可以分别发送消息,分别在双方的UITextView显示消息


了解:CFNetwork实现/封装的Socket接口(输入流和输出流Stream)

ViewController.m

<span style="font-size:14px;">#import "ViewController.h"
#import "GCDAsyncSocket.h"

@interface ViewController ()<GCDAsyncSocketDelegate>
@property (weak, nonatomic) IBOutlet UITextField *ipTextField;
//发送消息
@property (weak, nonatomic) IBOutlet UITextField *sendMsgTextField;
//显示消息
@property (weak, nonatomic) IBOutlet UITextView *showMsgTextView;
//发送端的socket对象
@property (nonatomic, strong) GCDAsyncSocket *clientSocket;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

}
//连接到主机(宿主机)
- (IBAction)connectToHost:(id)sender {
    //初始化socket对象
    self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    //指定ip+port,开始建立连接
    NSError *error = nil;
    [self.clientSocket connectToHost:self.ipTextField.text onPort:8888 withTimeout:-1 error:&error];
    if (!error) {
        NSLog(@"正在连接中.....");
    } else {
        NSLog(@"客户端无法连接:%@", error.userInfo);
    }
}
//发送消息到主机(写入输入流)
- (IBAction)sendMsgToHost:(id)sender {
    [self.clientSocket writeData:[self.sendMsgTextField.text dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
}

//连接成功
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    NSLog(@"连接成功!!!!!!!!");
    
    //处于等待接收数据状态
    [self.clientSocket readDataWithTimeout:-1 tag:0];
}
//客户端发送成功
- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag {
    NSLog(@"客户端发送成功.....");
}
//接收另一端发送来的消息(从输出流读数据)
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSString *readStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    self.showMsgTextView.text = [NSString stringWithFormat:@"%@\n%@", self.showMsgTextView.text, readStr];
    //处于等待接收数据状态
    [self.clientSocket readDataWithTimeout:-1 tag:0];
}
</span>

导入GCDAsyncSocket.m



HTTP协议(Hyper Text Transfer Protocol:超文本传输协议)

超文本: 不仅包含简单的文本, 还包含图片, 音频/视频(第一帧图片Frame)

用于从服务器传输超文本到本地浏览器的传输协议,规定客户端(浏览器)和服务器之间的数据传输格式。


协议的具体内容(理解) -> 格式:key/value

第一部分:请求部分(浏览器请求资源)

  a. 请求头(Request Header)

  b. 请求体(Request Body)

第二部分:响应部分(服务器返回资源)

 a. 响应头(Response Header)

 b. 响应体(Response Body)

  Content-Length: 请求的资源的总大小(更新下载进度)

  状态码: 200:成功;404:资源找不到


MIME类型: 指定客户端接收的类型(主类型/子类型)

MIME: 

文件:text/html; text/xml; text/plain…

图片:  image/png; image/gif; image/jpeg…

文档:application/pdf; application/rtf…


HTTP协议四个方法:

GET: 获取资源请求; 如果不指定请求的方法,默认就是GET

POST: 一般发送带参数的请求叫POST请求

PUT: 一般上传资源叫PUT请求

DELETE:删除指定的资源


例子:登录,发送用户名和密码两个参数;

选择一: http://www.pech.com/post/login?username=gaoyuanyuan&password=123123123

选择二:两个参数放到请求体中(相对安全)


2. NSURLConnection(过时) / NSURLSession


样例(理解):使用NSURLConnection请求百度主页

 【Demo04_NSURLConnection】

 掌握点:如何用代码获取状态码(200: 成功)

 NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];

 理解:涉及到HTTP协议MIME这个key

 界面:UIButton+UIWebView+UITextField

<span style="font-size:14px;">#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIWebView *webView;
@property (weak, nonatomic) IBOutlet UITextField *urlTextField;
@end

@implementation ViewController

- (IBAction)sendRequest:(id)sender {
    //1.NSURL对象
    NSURL *url = [NSURL URLWithString:self.urlTextField.text];
    //2.NSURLRequest对象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    //3.发送请求(NSURLConnection)
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        //主线程执行
        //从response对象中获取状态码Status code
        NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
        if (statusCode == 200) {
            //成功返回请求的主页数据data; 加载到webView
            [self.webView loadData:data MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:[NSURL fileURLWithPath:@"sdfs"]];
        }
    }];
}
</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值