网络编程基础1

网络编程基础1

URL

url(统一资源定位符 Uniform Resourse Locator)
通过一个URl,能够找到互联网上唯一的一个1个资源
URL 就是资源的地址,位置,互联网上的每个资源都有一个唯一的URL

URL的基本格式 = 协议://主机地址/路径

       http://www.baidu.com/ios/images/dong.jpg
       http://202.108.22.5/img/bdlogo.gif

http协议的作用

http全称是Hypertext Transfer Protocol ,超文本传输协议
规定客户端和服务器之间的数据传输格式
让客户端和服务器能够进行有效的沟通

客户端发送请求到服务器请求需要遵循http 协议因为传输的数据是二进制的 ,客户端响应服务器的信息也是需要遵守协议的

下边我们来写一个小的程序来体验一下网络编程的乐趣

   // 1. URL(确定要访问的网络资源页面,图片....路径)
   // m 是 mobile 的缩写
    NSURL *url = [NSURL URLWithString:@"http://m.baidu.com"];
    
   //2.客户端向服务器发送request请求 
     NSURLRequest *request = [NSURLRequest requestWithURL:url];
     
   //3. 建立网络连接,将请求(异步)发送给服务器
   // 多线程的目的就是将耗时操作放在后台,所有的网络请求都是耗时的
   // 几乎所有的网络请求,都应该是异步的  
   
   
   //下边的参数解释
      1.请求
      2.queue主队列 (对列的选择( 是否需要做耗时的操作))
      不耗时的话可以用主队列,耗时的话用新建队列
      3.完成时的回调block
     [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init]completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    // 服务器响应已经结束!
    //这句代码可以看出来我们的线程是一个异步线程
    NSLog(@"%@", [NSThread currentThread]);
    //输出二进制数据
    NSLog(@"%@", data);
    
    // 将二进制数据写入磁盘
    [data writeToFile:@"/Users/apple/Desktop/123" atomically:YES];


    //在当前的演练中,NSData 和 NSString 中保存的内容有什么区别?
    // 没有区别!
    // 所有的数据都是以二进制的形式保存在内存中的
    // NSString 提供了字符串的展现形式,以及字符串的操作方法
    // NSData 通常用于网络传输,以及写入文件
    NSString *xml = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    
    NSLog(@"%@", xml);
     }];
    //这句可以判断当我们执行完的时候我们先执行主线程的操作
    NSLog(@"come here");  

//在上述中可以利用最后一句的 NSLog(@”come here”); 来判断是同步的还是异步的
给大家普及一下编码格式的
链接:字符编码格式

socket网络编程

网络三要素:

1.IP地址(唯一标示一个网络中的计算机,不允许重复)

2.端口号(电话号码类似IP号码:端口号类似于分机号码)
端口号

3.传输协议(通讯的规则TCP/UDP)

ipv4 0-255,0-255,0-255,0-255 2的32次方 = 42亿

ipv6 同上原理 128位 2的128次方

域名:ip地址的一个速记名称

在网络访问中本质都是通过ip地址进行访问的
DNS服务器进行域名的解析

计算机—->路由器—–>DNS—->路由器再通过ip地址进行访问

DNS根服务器有504台大部分都在美国,根服务器记录世界全部的域名
本地回环地址:通过网卡访问本台机子

ip地址:通过路由器来访问本台机子

//我们可以用ping 127.0.0.1来看看书是不是我们的网卡坏了

传输协议概述

OSI网络模型
—-> OSI网络模型
假设由A向B发送一个信息(只能在应用层对应用层进行信息的交流)

(A) 应用层 ->表示层 -> 会话层 -> 传输层 -> 网络层 ->数据链路 层 -> 物理层 (上述过程叫做封包 ) ——-网线——(现在进行解包) (B)物理层 –> 数据链路层 –> 网络层 –> 传输层 —> 会话层 –> 表示层 –> 应用层

路由器一般都在(网络层) 交换价在(数据链路层)

传输层对应的是socket(协议TCP/UDP)

TCP/IP的参考模型
1.应用层(应用层,表示层,会话层)
2.传输层(TCP/UDP协议)
3.网络互连层
4.网络接口层

TCP/UDP协议(传输层)

TCP与UDP的区别

TCP(传输控制协议):

1)提供IP环境下的数据可靠传输(一台计算机发出的字节流会无差错的发往网络上的其他计算机,而且计算机A接收数据包的时候,也会向计算机B回发数据包,这也会产生部分通信量),有效流控,全双工操作(数据在两个方向上能同时传递),多路复用服务,是面向连接,端到端的传输;

2)面向连接:正式通信前必须要与对方建立连接。事先为所发送的数据开辟出连接好的通道,然后再进行数据发送,像打电话。

3)TCP支持的应用协议:Telnet(远程登录)、FTP(文件传输协议)、SMTP(简单邮件传输协议)。TCP用于传输数据量大,可靠性要求高的应用。

UDP(用户数据报协议,User Data Protocol)

1)面向非连接的(正式通信前不必与对方建立连接,不管对方状态就直接发送,像短信,QQ),不能提供可靠性、流控、差错恢复功能。UDP用于一次只传送少量数据,可靠性要求低、传输经济等应用。

  1. UDP支持的应用协议:NFS(网络文件系统)、SNMP(简单网络管理系统)、DNS(主域名称系统)、TFTP(通用文件传输协议)等。

3)大小限制在64K

总结:

TCP:面向连接、传输可靠(保证数据正确性,保证数据顺序)、用于传输大量数据(流模式)、速度慢,建立连接需要开销较多(时间,系统资源)。

UDP:面向非连接、传输不可靠、用于传输少量数据(数据包模式)、速度快。

socket(套接字层,插座)

参考:socket

Socket 就是为网络服务的一种机制

在Unix中,网络即是socket ,并不局限于TCP/UDP

Socket可以用于自定义协议

通信的两端都是Socket

网络通信其实就是socket之间的通信

数据在两个socket之间通过IO传输

Socket是纯C语言,跨平台

下边进入大家期待的socket编程开发(每个程序员都有一颗底层的心)

socket的五个步骤 socket—>connect—–>write=====read—–>read—->close

1.socket

domain: 协议域:AF_INET
type: Socket类型,SOCK_STREAM(流 TCP)/OCK_DGRAM(报文,提示:
在有些公司的程序员给服务器发送数据,会说:发送报文)

protocol: IPPROTO_TCP,提示:如果输入0,会根据第二个参数,自动选择协议

socket 如果>0 就是正确的
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);

2.connect(连接到服务器(实际上就是一台计算机))

参数:1.客户端socket
2.指向数据结构sockaddr的指针,其中包括目的端口和IP地址
C 语言中没有对象,实现都是通过结构体来实现的
3. 结构体数据长度
struct sockaddr_in serverAddress;

// 1> 地址 inet_addr 可以将 ip 地址转换成整数
// 提示:在网络上的使用的很多数据,需要做字节翻转
serverAddress.sin_addr.s_addr = inet_addr(“127.0.0.1”);

// 2> 端口 htons 可以将端口转换成整数
// 端口号同样要做字节翻转
serverAddress.sin_port = htons(12345);

// 3> 协议
serverAddress.sin_family = AF_INET;

// 在 C 语言中,通常传递结构体的指针同时,会传递结构体的尺寸

int result = connect(clientSocket, (const struct sockaddr *)&serverAddress, sizeof(serverAddress));

3.write(发送数据给服务器)

参数

1> 客户端socket

2> 发送内容地址

3> 发送内容长度

4> 发送方式标志,一般为0

返回值
如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR

提示:在很多C语言框架中,会将基本数据类型进行封装,使用的时候,便于后续框架的调整
*/
// 在 UTF8 编码中,一个中文对应 3 个字节

NSString *msg = @”约吗?”;

ssize_t sendLen = send(clientSocket, msg.UTF8String,
strlen(msg.UTF8String), 0);

NSLog(@”%ld %tu %ld”, sendLen, msg.length,
strlen(msg.UTF8String));

4. 从服务器接收数据

/**
参数

  1. 客户端socket

  2. 接收内容的空间

  3. 接收内容空间的长度

  4. 标记,如果是0,表示阻塞式,一直等到服务器的响应
    返回值
    接收到数据的长度
    */
    // 定义一个空的数组,准备接收数据
    uint8_t buffer[1024];

// 在 C 语言中,数组的名字,是指向数组第一个元素的指针
ssize_t recvLen = recv(clientSocket, buffer, sizeof(buffer), 0);

NSLog(@"接收到 %ld 字节", recvLen);

// 1> 取二进制数据
NSData *data = [NSData dataWithBytes:buffer length:recvLen];

// 2> 转换成字符串
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

NSLog(@"%@", str);
5. 关闭连接

close(clientSocket);

在网络上发送的地址和我们实际的现实的不一样,是利用字节反转来做的
127.0.0.1
127对应的16进制为:0X7F
127.0.0.1对应的是:0X7F00001
然后再字节反转并转换10进制:16777343

终端下监听端口号码:12345 nc -lk 12345

我们可以封装一下,做成一个聊天系统

- (BOOL)connectToHost:(NSString *)host port:(int)port {
  1. socket
      self.clientSocket = socket(AF_INET, SOCK_STREAM, 0);
      NSLog(@"%d", self.clientSocket);

  2. 连接到另外一台计算机
     struct sockaddr_in serverAddress;
     
  1> 地址 inet_addr 可以将 ip 地址转换成整数
  提示:在网络上的使用的很多数据,需要做字节翻转
     serverAddress.sin_addr.s_addr = inet_addr(host.UTF8String);
     
 2> 端口 htons 可以将端口转换成整数
 端口号同样要做字节翻转
    serverAddress.sin_port = htons(port);
 3> 协议

    serverAddress.sin_family = AF_INET;

 在 C 语言中,通常传递结构体的指针同时,会传递结构体的尺寸
    int result = connect(self.clientSocket, (const struct sockaddr *)&serverAddress, sizeof(serverAddress));

    return (result == 0);
    }


   - (NSString *)sendAndRecv:(NSString *)msg {
 
        提示:在很多C语言框架中,会将基本数据类型进行封装,使用的时候,便于后续框架的调整
    在 UTF8 编码中,一个中文对应 3 个字节
    ssize_t sendLen = send(self.clientSocket,         
    msg.UTF8String, strlen(msg.UTF8String), 0);

    NSLog(@"%ld %tu %ld", sendLen, msg.length,         
    strlen(msg.UTF8String));


    uint8_t buffer[1024];

    ssize_t recvLen = recv(self.clientSocket, buffer,         
    sizeof(buffer), 0);

    NSLog(@"接收到 %ld 字节", recvLen);

    取二进制数据
    NSData *data = [NSData dataWithBytes:buffer length:recvLen];
    转换成字符串
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    return str;
   }

          
- (void)disconnect {
      // 5. 关闭连接
   close(self.clientSocket);

}

//根据封装的东西来加载socket网站
— 请求头 —
1> 请求行
GET / HTTP/1.1

GET 表示从服务器”拿”数据

/ 访问服务器的根目录

HTTP/1.1 HTTP的协议以及版本

2> 请求头
Host: 要访问的主机

User-Agent: 用户代理,告诉服务器客户端的类型

Accept: 告诉服务器客户端支持的数据格式

Accept-Language: 告诉服务器客户端支持的语言

Accept-Encoding: 告诉服务器客户端支持的解压缩类型

HTTP请求本身的格式,是字符串格式的,最末一行,以 \n\n 结束,表示所有请求的内容发送完毕,服务器可以处理!

提示:key 值是 HTTP 协议定义的,不能随意更改!

— 响应 —
1> 状态行

HTTP/1.1 200 OK

HTTP/1.1 HTTP的协议以及版本

200 状态码(404)

2XX 成功

4XX 客户端错误

5XX 服务器错误

2> 响应头,服务器告诉客户端的一些信息
提示:响应的信息,通常在开发“下载”功能时,才会使用,平时用不着

Date: 响应日期
Server: 服务器的信息

// 文件长度
Content-Length: 24

3> 数据实体,从服务器返回的二进制数据!

//代码实现见下方

 // http 端口是 80
if ([self connectToHost:@"127.0.0.1" port:80]) {
    NSLog(@"连接成功");
}

// 发送消息给 web 服务器
// 建立请求字符串
  NSString *request = @"GET /ios.m HTTP/1.1\n"
  "Host: localhost\n"
  "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:36.0) Gecko/20100101 Firefox/36.0\n"
  "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\n"
  "Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3\n"
  "Accept-Encoding: gzip, deflate\n\n";

NSLog(@"%@", [self sendAndRecv:request]);

//根据上述封装的函数来做socket编程加载百度页面

// http 端口是 80
    if ([self connectToHost:@"61.135.169.125" port:80]) {
      NSLog(@"连接成功");
     }

// 发送消息给 web 服务器
// 建立请求字符串
      NSString *request = @"GET / HTTP/1.1\n"
     "Host: www.baidu.com\n"
     "User-Agent: iPhone AppleWebKit\n\n";

// 对结果的处理
     NSString *result = [self sendAndRecv:request];
// 找 \r\n 的出现的位置
     NSRange range = [result rangeOfString:@"\r\n\r\n"];

// 判断是否找到
    if (range.location == NSNotFound) {
      NSLog(@"html 错误");
      return;
    }

      NSString *html = [result substringFromIndex:range.location];

      NSLog(@"%@", html);
     [self.myWebView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://www.baidu.com"]];
智能家居

参考:智能家居

心跳包:(涉及到我们长连接和短连接问题)

总结:因为现在需要用到socket编程所以就临时学习了一下socket编程,socket编程是在我们的osi模拟模型的传输层,并且有TCP/UDP协议,从中学习到了tcp/udp的区别,从里边学到了socket编程的五个步骤都是跟C语言相关的函数,也学习到了socket如何封装,然后搭建自已的socket网站和聊天系统,了解了一些socket底层的实现原理

    原文作者:董军1990
    原文地址: https://www.jianshu.com/p/4197057ff4c4
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞