iOS开发网络篇—Socket编程

iOS开发网络篇—Socket编程,第1张

一、网络各个协议:TCP/IP、SOCKET、HTTP等

网络七层由下往上分别为物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

其中物理层、数据链路层和网络层通常被称作媒体层,是网络工程师所研究的对象;

传输层、会话层、表示层和应用层则被称作主机层,是用户所面向和关心的内容。

http协议对应于应用层

tcp协议对应于传输层

ip协议对应于网络层

三者本质上没有可比性。 何况HTTP协议是基于TCP连接的。

TCP/IP是传输层协议,主要解决数据如何在网络中传输;而HTTP是应用层协议,主要解决如何包装数据。

我 们在传输数据时,可以只使用传输层(TCP/IP),但是那样的话,由于没有应用层,便无法识别数据内容,如果想要使传输的数据有意义,则必须使用应用层 协议,应用层协议很多,有HTTP、FTP、TELNET等等,也可以自己定义应用层协议。WEB使用HTTP作传输层协议,以封装HTTP文本信息,然 后使用TCP/IP做传输层协议将它发送到网络上。Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API),通过Socket,我们才能使用TCP/IP协议。

二、Http和Socket连接区别

相信不少初学手机联网开发的朋友都想知道Http与Socket连接究竟有什么区别,希望通过自己的浅显理解能对初学者有所帮助。

2.1、TCP连接

要想明白Socket连接,先要明白TCP连接。手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接。TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上。

建立起一个TCP连接需要经过“三次握手”:

第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连

接之前,TCP

连接都将被一直保持下去。断开连接时服务器和客户端均可以主动发起断开TCP连接的请求,断开过程需要经过“四次握手”(过程就不细写了,就是服务器和客

户端交互,最终确定断开)

2.2、HTTP连接

HTTP协议即超文本传送协议(HypertextTransfer Protocol ),是Web联网的基础,也是手机联网常用的协议之一,HTTP协议是建立在TCP协议之上的一种应用。

HTTP连接最显著的特点是客户端发送的每次请求都需要服务器回送响应,在请求结束后,会主动释放连接。从建立连接到关闭连接的过程称为“一次连接”。

1)在HTTP 1.0中,客户端的每次请求都要求建立一次单独的连接,在处理完本次请求后,就自动释放连接。

2)在HTTP 1.1中则可以在一次连接中处理多个请求,并且多个请求可以重叠进行,不需要等待一个请求结束后再发送下一个请求。

于HTTP在每次请求结束后都会主动释放连接,因此HTTP连接是一种“短连接”,要保持客户端程序的在线状态,需要不断地向服务器发起连接请求。通常的

做法是即时不需要获得任何数据,客户端也保持每隔一段固定的时间向服务器发送一次“保持连接”的请求,服务器在收到该请求后对客户端进行回复,表明知道客

户端“在线”。若服务器长时间无法收到客户端的请求,则认为客户端“下线”,若客户端长时间无法收到服务器的回复,则认为网络已经断开。

三、SOCKET原理

3.1、套接字(socket)概念

套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题。多个TCP连接或多个应用程序进程可能需要通过同一个

TCP协议端口传输数据。为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了套接字(Socket)接口。应

用层可以和传输层通过Socket接口,区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务。

3.2 、建立socket连接

建立Socket连接至少需要一对套接字,其中一个运行于客户端,称为ClientSocket,另一个运行于服务器端,称为ServerSocket。

套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。

服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。

客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户

端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

3.3、SOCKET连接与TCP连接

创建Socket连接时,可以指定使用的传输层协议,Socket可以支持不同的传输层协议(TCP或UDP),当使用TCP协议进行连接时,该Socket连接就是一个TCP连接。

3.4、Socket连接与HTTP连接

于通常情况下Socket连接就是TCP连接,因此Socket连接一旦建立,通信双方即可开始相互发送数据内容,直到双方连接断开。但在实际网络应用

中,客户端到服务器之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致

Socket 连接断连,因此需要通过轮询告诉网络,该连接处于活跃状态。

而HTTP连接使用的是“请求—响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据。

多情况下,需要服务器端主动向客户端推送数据,保持客户端与服务器数据的实时与同步。此时若双方建立的是Socket连接,服务器就可以直接将数据传送给

客户端;若双方建立的是HTTP连接,则服务器需要等到客户端发送一次请求后才能将数据传回给客户端,因此,客户端定时向服务器端发送连接请求,不仅可以

保持在线,同时也是在“询问”服务器是否有新的数据,如果有就将数据传给客户端。

这里我们使用Socket实现一个聊天室的功能,关于服务器这里的就不介绍了

@interfaceViewController (){

NSInputStream *_inputStream//对应输入流

NSOutputStream *_outputStream//对应输出流

}

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputViewConstraint

@property (weak, nonatomic) IBOutlet UITableView *tableView

@property (nonatomic, strong) NSMutableArray *chatMsgs//聊天消息数组

@end

懒加载这个消息数组

//从主运行循环移除

//1.建立连接

//定义C语言输入输出流

//把C语言的输入输出流转化成OC对象

//设置代理

//把输入输入流添加到主运行循环

//不添加主运行循环 代理有可能不工作

//打开输入输出流

//登录

//发送用户名和密码

//在这里做的时候,只发用户名,密码就不用发送

//如果要登录,发送的数据格式为 "iam:zhangsan"

//如果要发送聊天消息,数据格式为 "msg:did you have dinner"

//登录的指令11NSString *loginStr =@"iam:zhangsan"

//把Str转成NSData

//建立一个缓冲区 可以放1024个字节

//返回实际装的字节数

//把字节数组转化成字符串

//从服务器接收到的数据

//聊天信息

//刷新表格

//发送数据

//发送完数据,清空textField

//数据多,应该往上滚动

}

//监听键盘

//获取窗口的高度

//键盘结束的Frm

//获取键盘结束的y值

对于初学者而已,我们学习的网络编程(如TCP,UDP编程),我们通常都是在局域网内进行通信测试,有时候我们或者会想,我们现在写的内网网络数据和外网的网络数据有什么不同,我们内网的数据是如何走出外网的呢?

再者,我们大多人都是使用宽带上网,结果发现,A 和 B 的局域网 IP 都是192.168.31.11,当他们都访问百度浏览网页时,百度服务器回复数据时,如何区分是给 A 还是给 B 呢?

公有 IP 和私有 IP 的区别

首先,我们需要了解一下什么是公有 IP 和私有 IP ?

公有地址(Public address):由 Inter NIC(Internet Network Information Center 因特网信息中心)负责。这些 IP 地址分配给注册并向Inter NIC提出申请的组织机构,公有 IP 全球唯一,通过它直接访问因特网(直接能上网)。

私有地址(Private address):属于非注册地址,专门为组织机构内部使用,说白了,私有 IP 不能直接上网。

而我们平时通过运营商(电信、移动、联通宽带等)上网,家里面通过路由器分出来的 IP 都是私有 IP(局域网 IP),大家可能会疑问,我们可以上网啊,怎么会是私有 IP 呢?

租用(申请)公有 IP 是需要钱的。 运营商买了一些公有 IP,然后通过这些公有 IP 分出来,再分给一个一个的用户使用。这个过程有点类似于,我们去安装了宽度,通过路由器分出几个 IP,让好几个人都能上网,当然运营商通过公有 IP 分出来的过程肯定比这个复杂多了。所以,我们平时上网用的 IP 是私有 IP,真正拥有公有 IP 的是运营商(当然,我们可以租用一个公有 IP )。所以,A 家庭的局域网 IP 和 B 家庭的局域网 IP 相同很正常,但是,最终 A 和 B 能上网(数据走出去)还是通过运营商的公有 IP,毕竟,公有 IP 的资源有限,这一片区域的用户使用的很有可能(实际上就是这样的)是同一个公有 IP,这样的话,又回到前面的问题,假如 A 和 B 的局域网 IP 相同(192.168.31.11),当他们同时访问百度服务器的时候,百度服务器如何区分哪个是 A,哪个是 B 呢?

端口映射

接下来,给大家介绍一下什么是端口映射?

端口映射是 NAT 的一种,它将外网主机的 IP 地址的一个端口映射到内网中一台机器,提供相应的服务。当用户访问该 IP 的这个端口时,服务器自动将请求映射到对应局域网内部的机器上。

现在市场上的家庭路由器都具备 NAT 功能,也可以实现端口映射。下图为小米路由器的端口映射设置图:

我们平时经过路由器,通过宽带,最终去到运营商那边,数据是从运营商出去,最终数据是回到运营商那边,运营商再把数据发送到用户的电脑。

路由器,至少有两个端口:WAN 口和 LAN 口。

WAN:接外部 IP 地址用,通常指的是出口,转发来自内部 LAN 接口的 IP 数据包,这个口的 IP 是唯一的。

LAN:接内部 IP 地址用,LAN 内部是交换机。

这里,我们简化这个过程,我们把运营商当做一个 NAT 设备。

为了方便大家理解,我们把 IP 的转化方向反过来分析(准确来说,公网转局域网)。

A 电脑的 IP 是局域网 IP(192.168.31.11),这个 IP(192.168.31.11)是从路由器的 lan口分配的。

当我们上百度的时候,经过路由器的 wan口,进行相应的IP、端口转化:192.168.31.11:80 ->10.221.0.24:8080,所以,从 wan口出去的地址为:10.221.0.24:8080。

最后,经过运营商,运营商那边会做相应的端口映射(而且是动态端口映射),子网 IP(10.221.0.24:8080)转化为公网 IP(128.0.0.1:8888),通过这个公网 IP 去访问百度服务器。

同理,B 的过程也是一样。通过这样的层层端口映射,最终保证地址(IP + 端口)的唯一性。A 和 B 访问百度服务器,尽管它们的局域网 IP 是一样的,但是最终它们访问百度的地址(IP + 端口)是唯一的,所以,百度服务器回复时,原路返回时能够区分到底给谁回。

作为可以实现远程连接的内外网转换工具花生壳来说,它是一个动态域名解析软件。当您安装并注册花生壳动态域名解析软件,无论您在任何地点、任何时间、使用任何线路,均可利用这一服务建立拥有固定域名和最大自主权的互联网主机。“花生壳动态域名解析软件”支持的线路包括普通电话线、ISDN、ADSL、有线电视网络、双绞线到户的宽带网和其它任何能够提供互联网真实IP的接入服务线路,而无论连接获得的IP属于动态还是静态。 花生壳动态域名解析软件为千万的域名提供动态域名解析服务,并广泛应用于网站建设、视频监控、遥感测绘、FTP、VPN、企业OA、ERP等应用领域。

一直用Http用多了 复习一下基础

Unity通讯一般分为2类

Http : 应用层 Unity内置的UnityWebRequest类进行通信(之前写过一个分发器垃圾框架)用于交互量比较小

Socket:传输层 比较底层 实现TCP/UDP 用于频繁的通信

这个是基于TCP 和IP传输不同消息

这个是三种常见的网络层次划分

基本数据单位为帧

主要的协议:以太网协议

基本数据单位为IP数据报;

IP协议(Internet Protocol,因特网互联协议)

ICMP协议(Internet Control Message Protocol,因特网控制报文协议)

ARP协议(Address Resolution Protocol,地址解析协议)

RARP协议(Reverse Address Resolution Protocol,逆地址解析协议)

包含的主要协议:TCP协议(Transmission Control Protocol,传输控制协议)、UDP协议(User Datagram Protocol,用户数据报协议)

数据传输基本单位为报文

包含的主要协议:

FTP(文件传送协议)、Telnet(远程登录协议)、DNS(域名解析协议)、SMTP(邮件传送协议),POP3协议(邮局协议),HTTP协议(Hyper Text Transfer Protocol)。

分配给用户上网使用的网际协议

目前IPv4多 比如192.168.1.1

新的IPv6(因为IPv4数量不够分配)如3ffe:3201:1401:1280:c8ff:fe4d:db39:1984。

Internet最基本的协议

TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。

可靠的协议 通过三次握手建立的面向连接通信协议

3次握手 四次挥手 实习生常考

TCP连接建立过程(三次握手):

1.首先Client端发送连接请求报文

2.Server段接受连接后回复ACK报文,并为这次连接分配资源。

3.Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。

TCP连接断开过程(四次挥手):

1.Client端发起中断连接请求(FIN报文)

2.Server端接到FIN报文后,发送ACK服务器还有消息没发完让Client待命,Client端就进入FIN_WAIT,继续等待Server端的FIN报文

3.Server端确定数据已发送完成,则向Client端发送FIN报文,

4.Client端收到FIN报文后发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传,Server端收到ACK后 关闭,Client等待了2MSL后依然没有收到回复客户端也关闭

SYN:"synchronize"请求同步标志;;ACK:"acknowledge"确认标志";FIN:"Finally"结束标志。

为什么要三次握手?

防止因为网卡导致Sever收到多次Client请求 建立N个监听 造成资源浪费

为什么要四次挥手?

自己不请求直接关闭 但是服务器还能给你发数据 服务器浪费资源 而且客户端也会强行接收

使用TCP的协议:FTP(文件传输协议)、Telnet(远程登录协议)、SMTP(简单邮件传输协议)、POP3(和SMTP相对,用于接收邮件)、HTTP协议等。

面向无连接的通讯协议

UDP通讯时不需要接收方确认,属于不可靠的传输 会丢包

UDP与TCP位于同一层,但它不管数据包的顺序、错误或重发

主要用于面向查询---应答的程序

每个UDP报文分UDP报头和UDP数据区两部分

UDP报头由4个域组成,其中每个域各占用2个字节

(1)源端口号;

(2)目标端口号;

(3)数据报长度;

(4)校验值。

使用UDP协议包括:TFTP(简单文件传输协议)、SNMP(简单网络管理协议)、DNS(域名解析协议)、NFS、BOOTP。

超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议

HTTP协议特点:

简单快速 灵活 无连接 无状态 支持B/S(浏览器/服务器)及C/S(客户端/服务器)模式。

URL

和服务器有一些频繁的交互 用http时不时请求 叫轮询 效率低下

soket可以理解为插座 插头接上了可以保持通信

端口:

每个Socket连接都是从一台计算机网卡的一个端口连接到另外一台计算机网卡的某个端口。

IP是房子的话 端口就是门

TCP端口和UDP端口相互独立 如TCP255端口 和UDP255端口 不冲突

周知端口

范围从0到1023,其中80端口分配给WWW服务,21端口分配给FTP服务等。

浏览器的地址栏里输入一个网址的时候是不必指定端口号的,因为在默认情况下WWW服务的端口是“80”。

网络服务是可以使用其他端口号的 比如 网址:8080

但是有些系统协议使用固定的端口号,它是不能被改变的,比如139 端口专门用于NetBIOS与TCP/IP之间的通信,不能手动改变。

自己开发时尽量不要使用1024之下的端口,可能会与系统端口冲突。

服务端:

创建socket对象

bind:绑定IP地址和端口

listen:开始监听绑定的IP地址和端口,等待客户端的连接

accept:如果有客户端发起连接,通过accept接受连接请求,连接成功后会复制一个socket出来用于和当前接受连接的客户端进行通信。(服务端最初创建的那个socket只是用来监听并建立连接用的,实际和客户端通信并不是最初的socket,而是在accept这一步会自动创建一个新的socket出来和客户端通信。)

read/write:使用新的socket读写数据

close:关闭socket,如果关闭的是服务端的监听socket,则无法接收新的连接,但是已经创建的和客户端的连接不会被关闭。

客户端:

创建socket对象

connect:连接服务端,连接成功后系统会自动分配端口

read/write:连接成功后,就可以进行数据的读写了,这里读写使用的socket还是第一步创建的socket对象。

close:关闭连接。

如果收到了长度为0的数据,则代表远程socket关闭了连接。

服务器:

创建socket对象

bind:绑定IP和端口,用于接收数据(注意这里绑定完就可以直接接收数据了,并不需要等待连接)

read/write:读写数据

客户端:

创建socket对象

read/write:读写数据,不需要先建立连接,直接给对应的IP+端口发送数据即可。

由于没有建立连接以及连接的保障,UDP在传输效率上会很高

UDP有一个功能是TCP所不具备的,那就是广播功能(UDP可以将消息发送到在同一广播网络上的每个主机 CS、魔兽争霸局域网对战)。

HTTP/HTTPS(比http更安全):小游戏 网页 间歇性发送链接 偶尔延迟。

TCP长连接: 卡牌游戏 某些mmo 客户端和服务器都可以独立发包 偶尔延迟

UDP:动作游戏 mmo 枪战 客户端和服务器都可以独立发包 无法接受延迟

可以混合使用你的MMO客户端也许首先使用HTTP去获取上一次的更新内容,然后使用UDP跟游戏服务器进行连接。

现在也有kcp 就是tcp和udp结合 快速安全可靠

简单直接的长连接

可靠的信息传输

数据包的大小没有限制

坑多 断线检测、慢速客户端响应阻塞数据包,对开放连接的各种dos攻击,阻塞和非阻塞IO模型

丢包会有阻塞机制(一般是重发 tcp相反) 所以手机游戏ping跳1000就这个原因

只使用一个socket进行通信

快速

基于数据包构建

灵活 多种方式处理延迟

很多东西没有要自己构建

不可靠

丢包

客户端直接开始进行计算而不等待服务端确认是一种典型的隐藏延迟的技术(容易被抓包篡改)。

我们到底是使用TCP还是UDP取决于我们能否隐藏延迟。

比如TCP 在棋牌 卡牌游戏 卡1S无所谓 在动作游戏moba游戏就很致命

可靠的UDP/kcp和TCP不一样,要去实现一个特殊的阻塞控制,而且还要保证可靠性,也可以使用许多支持可靠通信的UDP库,但是库一般为了通用会降低某种新能,自己根据项目情况写可以发挥到极致

如果不知道用什么就TCP


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/652419.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-07-23
下一篇2023-07-23

发表评论

登录后才能评论

评论列表(0条)

    保存