Python中的网络编程

目录

一、引入

二、网络编程

三、软件开发架构

1、客户端服务端概念

2、C/S架构

3、B/S架构

四、计算机网络

1、网络协议(TCP/IP协议族)

2、TCP协议

3、UDP协议

4、TCP和UDP的对比

5、OSI模型

五、Socket概念

1、理解Socket

2、Socket 发展史

1、基于文件型

2、基于网络型

3、socket参数详解

4、基于TCP协议的Socket使用

5、基于UDP协议的Socket使用


一、引入

我们可以在我们的电脑上和别人聊天,可以在自己的电脑上向网盘中上传、下载内容。这些都是两个程序在通信。由于在不同机器上的程序需要通信,才产生了网络。

 

二、网络编程

就是通过网络让不同计算机上运行的程序可以进行通信。

例如两台电脑上的qq通过网络进行相互聊天。

 

三、软件开发架构

两个程序之间通讯的应用大致可以分为两种:

第一种是应用类程序:qq、微信、网盘、优酷这一类是属于需要安装的桌面应用

第二种是web类程序:用户只需要浏览器即可访问程序。常见的web类应用程序

比如百度、知乎、CSDN等使用浏览器访问就可以直接使用。

不管是应用类程序还是web类程序,这些应用的本质其实都是两个程序之间的通讯。

而这两个分类又对应了两个软件开发的架构~

1、客户端服务端概念

客户端:就是我们常用的程序例如qq、微信,浏览器等等。

服务端:要一直运行着给别人提供服务的机器(电脑、服务器)。

例如现在我使用的CTS软件给同学们提供服务,我的电脑就是服务端(服务器)

2、C/S架构

C/S即:Client与Server ,中文意思:客户端与服务器端架构。

这里的客户端一般泛指客户端应用程序exe,程序需要先安装后,才能运行在用户的电脑上,对用户的电脑操作系统环境依赖较大。

3、B/S架构

B/S即:Browser与Server,中文意思:浏览器端与服务器端架构。

只需在浏览器上通过HTTP去请求服务器端相关的资源(网页资源)。

四、计算机网络

首先说明一下每台电脑在网络世界中都有一个全球唯一的标识就是ip地址。

那ip地址是什么呢?听我娓娓道来。我们的电脑上网需要有硬件设施网线和网卡,网卡用来链接网线。网卡上有全球上唯一的物理地址(mac),长度为48位2进制,通常由12位16进制数表示(前六位是厂商编号,后六位是流水线号)

但是链接mac地址记起来很麻烦因此出现了ip地址。范围0.0.0.0-255.255.255.255。

一个ip地址通常写成四段十进制数,例:172.16.10.1

通过 ip地址 就能找到mac地址,中间遵循了ARP(Address Resolution Protocol)协议,

中文叫:地址解析协议, 是根据IP地址取物理地址的一个TCP/IP协议。

一个特殊的地址 127.0.0.1 本地回环地址,访问自己电脑上的程序。

 

我们通过了ip地址找到了具体的某一台电脑,那我们怎么找到了想访问的应用呢?例如两台

QQ进行聊天案例,怎样找到另外一台电脑上的QQ程序呢?就需要通过电脑上的端口了。

电脑上的每一个应用程序想运行必须占一个端口号。并且端口号同时间只能被一个应用程序占用。

每一台电脑上一共有65536个端口,端口的范围是0~65535。一般0~1023被一些其他应用已经占用,因此我们一般从1024开始指定端口。

 

1、网络协议(TCP/IP协议族)

网络协议就是为了能让计算机网络中进行数据交换而建立的规则、标准;

例如下载软件然后如果不同意协议就不能继续下一步,同样的道理在互联网中,如果不遵循互联网协议就不能访问到资源;

互联网上有上百种协议,但是最重要的两个协议是TCP协议和IP协议,因此我们将上百种协议统称为TCP/IP 协议族。TCP/IP协议族,根据协议的功能的不同抽象成了4层。

应用层:TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等

传输层:TCP,UDP

网络层:IP,ICMP,OSPF,EIGRP,IGMP

数据链路层:SLIP,CSLIP,PPP,MTU

 

据传输的时候先将数据从应用层传递到传输层,然后再从传输层传递到网络层,然后再传递到链路层,最后在通过物理传输介质(网线)传递数据。大家想一下为什么要一层一层的传递,而不是直接传递数据呢?是为了保证数据能够稳定的传输到对方电脑上去。

举个买手机的例子

这张图表达的意思是一个人买了一个手机,然后卖方邮寄的一个完整的过程。卖方在发送手机的时候为了不让手机受到损坏,每一个过程都要进行包装,例如卖家至给快递公司了一个手机盒子,快递公司添加了一个外层包装,给飞机公司,飞机公司有添加了一次保护膜。

送往客户手中的时候,从飞机上卸下来手机时,将保护膜去掉,然后客户拿到手机时,先把外层快递的包装盒给拆开,然后将手机盒拆开,最后拿到手机。

这个过程发送方在组包,一层层变大,接收方在解包一层层变小。

言外之意就是我们电脑上的数据想要发生到你的电脑上需要通过一层一层的传输,在传输过程中为了保证数据不丢失,需要在每一层的时候添加一些额外的内容。那每一层都添加了哪些内容呢?

例如 应用层指的是QQ通信需要有自己的协议,迅雷下载下载东西有自己的协议,浏览器访问互联网 使用的是HTTP协议。

 

例如现在发送一个‘hello’走的过程是:

在应用层加上自己的协议 例如 xx hello。

传递到了传输层,添加了源端口和目的端口。

走到了网络层,会在前面添加上 源ip地址和目的ip。

走到链路层,添加源mac 地址和目的mac地址。

然后通过网线传输到对方的电脑上,先判断是不是我的mac地址,如果是就减去mac,在往上到网络层,判断是不是我的ip地址,如果是就减去,依次往上走,直到qq。中间如果有一层不对就把数据扔掉。对方就不能获取发送过来的信息。

2、TCP协议

TCP(Transmission Control Protocol)可靠的、面向连接的协议

(什么是面向连接呢?就是发送消息之前先建立连接然后再发送消息例如打电话场景,在网络中具体指的是三次握手)

TCP协议特点:数据安全,速度略低。分为客户端和服务端。

使用TCP的应用:Web浏览器;电子邮件等程序。

TCP的三次握手和4次挥手

TCP三次握手:

三次握手就是客户端和服务器进行通信的时候有三次交流。例如如下:

客户端问服务端你准备好了吗(第一次),服务端告诉客户端装备好了,并且问客户端你准备好了吗(第二次),客户端说我准备好了(第三次)。

第一次握手:是客户端让服务器准备好资源。

第二次握手:服务端资源准备好了并且服务端问客户端资源有没有准备好。

第三次握手:客户端资源也准备好了。接下来才真正的发生数据。

 

真正进行3次握手的时候发送的是值。

 

第一次客户端装备了一个值例如是11,发送给了服务端,服务端如果准备好了就将11+1变成12再发送给客户端,表示服务端准备好了资源。

服务怎么知道客户端准备好了资源呢?服务器给客户端发送一次数据例如33,客户端如果准备好了就再将数据加1 33+1 =34 发送给服务端,服务端接受到后就表明客户端准备好了。这样4次才知道双方准备好了资源。这里发生了4次,不是3次,

当用户打开一个网站的时候我们想尽快的看到内容,因此能减少的次数尽量减少

因此最终将12和44 的数据变成了一次请求。发生12表示给客户端回答的值,44表示

我向客户端发送的值。提高传输的效率。节约时间。

这个12和44怎么区分是请求的还是应答的呢?我们可以给数据添加一个标记

Syn 11 来标记请求, ack 标记应答

三次握手:

TCP是因特网中的传输层协议,使用三次握手协议建立连接。当主动方发出SYN连接请求后,等待对方回答SYN+ACK[1],并最终对对方的 SYN 执行 ACK 确认。这种建立连接的方法可以防止产生错误的连接。[1]

TCP三次握手的过程如下:

客户端发送SYN(SEQ=x)报文给服务器端,进入SYN_SEND状态。

服务器端收到SYN报文,回应一个SYN (SEQ=y)ACK(ACK=x+1)报文,进入SYN_RECV状态。

客户端收到服务器端的SYN报文,回应一个ACK(ACK=y+1)报文,进入Established状态。

三次握手完成,TCP客户端和服务器端成功地建立连接,可以开始传输数据了。

数据传输:

每传递一次消息,服务端都会告诉客户端说收到消息了。这样确保数据不会丢失。因此我们说TCP是可靠地面向连接(连接一直连着)的传输协议

 

四次挥手

客户端给服务器说再见,服务器给客户端说拜拜,服务端告诉客户端我也不和你玩了,客户端说不玩就不玩。

第一次,客户端告诉服务端我不会给你发数据了,第二次服务端告诉客户端我收到你发生的信息了,第三次服务端给客户端发生数据说我也不给你发了,第四次客户端给服务端说我知道了。

 

四次挥手:

建立一个连接需要三次握手,而终止一个连接要经过四次挥手。

(1) 某个应用进程首先调用close,称该端执行“主动关闭”(active close)。该端的TCP于是发送一个FIN分节,表示数据发送完毕。

(2) 接收到这个FIN的对端执行 “被动关闭”(passive close),这个FIN由TCP确认。

注意:FIN的接收也作为一个文件结束符(end-of-file)传递给接收端应用进程,放在已排队等候该应用进程接收的任何其他数据之后,因为,FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收。

(3) 一段时间后,接收到这个文件结束符的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN。

(4) 接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN。[1]

3、UDP协议

UDP协议:面向无连接,数据不安全,速度快。不区分客户端与服务端。

用于网络电话,在线视频网络会议等等,要求实时性比较高(数据传输快)不能有延迟。

当应用程序希望通过UDP与一个应用程序通信时,传输数据之前源端和终端不建立连接。

当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。

因此UDP是不可靠无连接的协议。因为有可能数据会丢失。

4、TCP和UDP的对比

TCP--提供的是面向连接、可靠的服务。当客户和服务器彼此交换数据前,必须先在双方之间建立一个TCP连接,之后才能传输数据。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。

UDP--是一个简单的不可靠的运输层协议。它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快

 

5、OSI模型

OSI模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为OSI参考模型或七层模型

OSI模型又将TCP/IP协议族的四层进行了具体划分,划分成了7层。

每次运行常见的协议

五、Socket概念

1、理解Socket

首先我们写的网络编程,属于应用层,当我们写好了程序后,需要将数据发送给运输层,

但是应用层和运输层通信需要遵循相关协议,关键是我们不了解运输层的协议,那该怎么办呢?因此提供了Socket层,Socket英文插座,插口,套接字意思。

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,让Socket去组织数据,以符合指定的协议。(面向对象的特点,我们只负责编写逻辑即可,不用去管TCP/IP具体的格式,Sockect会帮我们做)。

2、Socket 发展史

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

1、基于文件型

套接字家族的名字:AF_UNIX

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

 

2、基于网络型

套接字家族的名字:AF_INET

(还有AF_INET6被用于ipv6,还有一些其他的地址家族,不过,他们要么是只用于某个平台,要么就是已经被废弃,或者是很少被使用,或者是根本没有实现,所有地址家族中,AF_INET是使用最广泛的一个,python支持很多种地址家族,但是由于我们只关心网络编程,所以大部分时候我么只使用AF_INET)

3、socket参数详解

socket.socket(family=AF_INET,type=SOCK_STREAM)

family

地址系列应为AF_INET(默认值),AF_INET6,AF_UNIX,AF_CAN或AF_RDS。
(AF_UNIX 域实际上是使用本地 socket 文件来通信)

type

套接字类型应为SOCK_STREAM(默认值),SOCK_DGRAM,SOCK_RAW或其他SOCK_常量之一。
SOCK_STREAM 是基于TCP的,有保障的(即能保证数据正确传送到对方)面向连接的SOCKET,多用于资料传送。 
SOCK_DGRAM 是基于UDP的,无保障的面向消息的socket,多用于在网络上发广播信息。

 

4、基于TCP协议的Socket使用

Socket是基于tcp协议的,tcp是基于链接的,因此在通讯开始之前,一定要先建立相关的链接,才能发送数据。必须先启动服务端,然后再启动客户端去链接服务端。

写一个聊天工具:

(1)服务端

import socket

server_sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip_port = ('127.0.0.1', 9995)
server_sk.bind(ip_port)
server_sk.listen(128)

new_socket, addr = server_sk.accept()
while 1:
    ret = new_socket.recv(1024).decode('utf-8')
    print('客户端发送过来的数据是:', ret)
    if ret == 'bye':
        break
    content = input('请输入内容:')
    new_socket.send(content.encode('utf-8'))
    if content == 'bye':
        break
new_socket.close()
server_sk.close()

(2)客户端

import socket

client_sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ip_port = ('127.0.0.1', 9995)
client_sk.connect(ip_port)

# 先发送数据
while 1:
    ret = input('请输入内容--->')
    client_sk.send((ret.encode('utf-8')))
    if ret == 'bye':
        break
    content = client_sk.recv(1024).decode('utf-8')
    print('服务端发来的数据是:', content)
    if content == 'bye':
        break
client_sk.close()

 

5、基于UDP协议的Socket使用

udp是无链接的,启动服务之后可以直接接受消息,不需要提前建立链接

 

写一个聊天工具:

(1)服务端

import socket

sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sk.bind(('127.0.0.1', 9876))
while 1:
    content, addr = sk.recvfrom(1024)
    print('客户端发来了信息:', content.decode('utf-8'))
    if content.decode('utf-8') == 'bye':
        break
    inp = input('请输入内容:')
    sk.sendto(inp.encode('utf-8'), addr)
    if inp == 'bye':
        break
sk.close()

(2)客户端

 

 

import socket

sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
while 1:
    inp = input('请输入:')
    sk.sendto(inp.encode('utf-8'), ('127.0.0.1', 9876))
    if inp == 'bye':
        break
    ret, addr = sk.recvfrom(1024)
    print('这是服务端发来的消息:', ret.decode('utf-8'))
    if ret.decode('utf-8') == 'bye':
        break
sk.close()

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值