Python之路(第三十篇) 网络编程:socket、tcp/ip协议

1、客户端/服务器架构

1.硬件C/S架构(打印机)python

打印机做为一个服务端,电脑链接打印机进行打印编程

2.软件C/S架构设计模式

  互联网中到处是C/S架构浏览器

  如谷歌网站是服务端,你的浏览器是客户端(B/S架构也是C/S架构的一种)缓存

  腾讯做为服务端为你提供视频,你得下个腾讯视频客户端才能看它的视频)安全

C/S架构与socket的关系:服务器

咱们学习socket就是为了完成C/S架构的开发markdown

 

2、什么是tcp/ip协议

​ 计算机之间通信须要遵循必定的互联网协议,好比tcp/ip协议,大量的计算机之间进行通信组成了计算机网络,网络的核心即一堆协议,协议即标准,因为tcp/ip协议太过于复杂,这时须要用socket层对tcp/ip协议进行精简,提供相应的接口以便更加方便的调用。因此学习socket必定要先学习互联网协议。网络

互联网协议按照功能不一样分为osi七层或tcp/ip五层或tcp/ip四层架构

 

每层运行常见物理设备

 

TCP/IP 是一类协议系统,它是用于网络通讯的一套协议集合,传统上来讲 TCP/IP 被认为是一个四层协议。

 

1) 网络接口层:

物理层:主要是指物理层次的一些接口,好比电缆等.

提供计算机互通的物理介质, 基于电器特性发送高低电压(电信号),高电压对应数字1,低电压对应数字0

数据链路层:

定义电信号的分组方式,使用以太网协议封装数据格式(数据报头(18个字节双方地址+数据类型)+数据)

 

2) 网络层:

提供独立于硬件的逻辑寻址,实现物理地址与逻辑地址的转换.

在 TCP / IP 协议族中,网络层协议包括 IP 协议(网际协议),ICMP 协议( Internet 互联网控制报文协议),以及 IGMP 协议( Internet 组管理协议).

网络层引入一套新的地址用来区分不一样的广播域/子网,这套地址即网络地址(IPV4/IPV6)

3) 传输层:

为网络提供了流量控制,错误控制和确认服务.

在 TCP / IP 协议族中有两个互不相同的传输协议: TCP(传输控制协议)和 UDP(用户数据报协议).

创建端口到端口的通讯(应用软件使用的端口号)。

4) 应用层:

为网络排错,文件传输,远程控制和 Internet 操做提供具体的应用程序

 

数据包在 TCP / IP 协议中数据先由上往下将数据装包,而后由下往上拆包

在装包的时候,每一层都会增长一些信息用于传输,这部分信息就叫报头,当上层的数据到达本层的时候,会将数据加上本层的报头打包在一块儿,继续往下传递.

 

 

在拆包的时候,每一层将本层须要的报头读取后,就将剩下的数据往上传.

这个过程有点像俄罗斯套娃,因此有时候人们也会用俄罗斯套娃来形容这个过程.

 

tcp的三次握手四次挥手

 

三次握手:1.客户端对服务端发送同步请求(创建链接通道);2.服务端响应后,发送同步请求(创建链接通道)和发送确认数据(这里的两个请求被合并成一个了);3.客户端向服务端发送确认数据。

 

四次挥手:1.客户端发送端口结束包给服务端,2.服务端收到之后返回确认信息给客户端;3.服务端发送端口结束包给客户端;4.客户端确认信息返回给服务端。

 

区别:四次挥手的过程当中,服务端返回给客户端的确认信息以后不会马上关闭,有可能会继续给客户端发送数据,因此必须得有四次挥手

 

3、socket是什么

Socket是应用层与TCP/IP协议族通讯的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来讲,一组简单的接口就是所有,让Socket去组织数据,以符合指定的协议。

因此,咱们无需深刻理解tcp/udp协议,socket已经为咱们封装好了,咱们只须要遵循socket的规定去编程,写出的程序天然就是遵循tcp/udp标准的。

没有socket以前

 

有socket以后

 

 

为何socket翻译为套接字?

socket中文翻译为套接字,socket英文本义为孔和插座的意思。

 

 

套接字发展史及分类

套接字起源于 20 世纪 70 年代加利福尼亚大学伯克利分校版本的 Unix,即人们所说的 BSD Unix。 所以,有时人们也把套接字称为“伯克利套接字”或“BSD 套接字”。一开始,套接字被设计用在同 一台主机上多个应用程序之间的通信。这也被称进程间通信,或 IPC。套接字有两种(或者称为有两个种族),分别是基于文件型的和基于网络型的。

*基于文件类型的套接字家族*

套接字家族的名字:AF_UNIX

unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套接字进程运行在同一机器,能够经过访问同一个文件系统间接完成通讯

*基于网络类型的套接字家族*

套接字家族的名字:AF_INET

还有AF_INET6被用于ipv6,还有一些其余的地址家族,全部地址家族中,AF_INET是使用最普遍的一个,python支持不少种地址家族.

 

*family(socket家族)*

  • socket.AF_UNIX:用于本机进程间通信,为了保证程序安全,两个独立的程序(进程)间是不能互相访问彼此的内存的,但为了实现进程间的通信,能够经过建立一个本地的socket来完成

  • socket.AF_INET:(还有AF_INET6被用于ipv6,还有一些其余的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是不多被使用,或者是根本没有实现,全部地址家族中,AF_INET是使用最普遍的一个,python支持不少种地址家族,可是因为咱们只关心网络编程,因此大部分时候我么只使用AF_INET)

*socket type类型*

  • socket.SOCK_STREAM #for tcp

  • socket.SOCK_DGRAM #for udp

  • socket.SOCK_RAW #原始套接字,普通的套接字没法处理ICMP、IGMP等网络报文,而SOCK_RAW能够;其次,SOCK_RAW也能够处理特殊的IPv4报文;此外,利用原始套接字,能够经过IP_HDRINCL套接字选项由用户构造IP头。

  • socket.SOCK_RDM #是一种可靠的UDP形式,即保证交付数据报但不保证顺序。SOCK_RAM用来提供对原始协议的低级访问,在须要执行某些特殊操做时使用,如发送ICMP报文。SOCK_RAM一般仅限于高级用户或管理员运行的程序使用。

  • socket.SOCK_SEQPACKET #废弃了

 

套接字工做流程

一个生活中的场景。你要打电话给一个朋友,先拨号,朋友听到电话铃声后提起电话,这时你和你的朋友就创建起了链接,就能够讲话了。等交流结束,挂断电话结束这次交谈。 生活中的场景就解释了这工做原理。

​ 服务器端先初始化Socket,而后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端链接。在这时若是有个客户端初始化一个Socket,而后链接服务器(connect),若是链接成功,这时客户端与服务器端的链接就创建了。客户端发送数据请求,服务器端接收请求并处理请求,而后把回应数据发送给客户端,客户端读取数据,最后关闭链接,一次交互结束.

 

socket函数

服务端套接字函数

  • s.bind() 绑定(主机,端口号)到套接字

  • s.listen() 开始TCP监听

  • s.accept() 被动接受TCP客户的链接,(阻塞式)等待链接的到来

客户端套接字函数

  • s.connect() 主动初始化TCP服务器链接

  • s.connect_ex() connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

公共用途的套接字函数

  • s.recv() 接收数据

  • s.send() 发送数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完,可后面经过实例解释)

  • s.sendall() 发送完整的TCP数据(本质就是循环调用send,sendall在待发送数据量大于己端缓存区剩余空间时,数据不丢失,循环调用send直到发完)

  • s.sendto() 发送UDP数据

  • s.recvfrom()接收UDP数据 Receive data from the socket. The return value is a pair (bytes, address)

  • s.getpeername() 链接到当前套接字的远端的地址

  • s.close() 关闭套接字

  • socket.setblocking(flag) #True or False,设置socket为非阻塞模式,之后讲io异步时会用

  • socket.getaddrinfo(host, port, family=0, type=0, proto=0, flags=0) 返回远程主机的地址信息,例子 socket.getaddrinfo('google.com',80)

  • socket.getfqdn() 拿到本机的主机名

  • socket.gethostbyname() 经过域名解析ip地址

  • s.getsockopt() 返回指定套接字的参数

  • s.setsockopt() 设置指定套接字的参数

面向锁的套接字方法

  • s.setblocking() 设置套接字的阻塞与非阻塞模式

  • s.settimeout() 设置阻塞套接字操做的超时时间

  • s.gettimeout() 获得阻塞套接字操做的超时时间

面向文件的套接字的函数

  • s.fileno() 套接字的文件描述符

  • s.makefile() 建立一个与该套接字相关的文件

 

 

参考连接

[1]http://www.javashuo.com/article/p-kkrifpzc-r.html

[2]https://www.zhihu.com/question/21383903

相关文章
相关标签/搜索