python网络编程

  • Post author:
  • Post category:python


网络编程指的是:

在程序中实现两台计算机之间的通信。 Python提供了大量的内置模块和第三方模块用于支持各种网络访问,而且Python


语言在网络通信方面的优点特别突出,远远领先其他语言。


目录


一,网络编程基本概念


1,什么是IP地址?


2,IP地址的分类


2.1 公有地址


2.2 私有地址


3,本地服务器IP地址


4,Windows下常用的ip命令


5,什么是子网?子网掩码?


6,什么是网关?


7,什么是交换机?


8,什么是路由器?


9,什么是路由?


10,子网下的设备如何访问互联网?


11,什么是端口?


11.1 端口分配


11.2 公认端口(Well Known Ports):


11.3 注册端口(Registered Ports):


二,网络通信协议


1,一张神图


2,OSI网络协议七层模型


3,TCP/IP协议模型


4,TCP和UDP的区别?


4.1 TCP


4.2 UDP


4.3 TCP和UDP区别


5,TCP建立链接的三次握手


6,TCP断开连接的四次挥手


7,数据包与处理流程


7.1 什么是数据包?


7.2 数据包处理流程


三,socket套接字编程


1,什么是套接字编程?


2,socket()函数介绍


3,socket对象的方法一览


4,UDP编程实例


4.1 单工最简案例


4.2 单工持续通信


4.3 双工持续通信


5,TCP/IP编程实例


5.1 TCP/IP编程简介


5.2 TCP编程的实现过程


5.3 TCP单工通信服务端


5.4 TCP单工通信客户端


5.5 TCP单工持续通信服务端


5.6 TCP单工持续通信客户端


5.7 TCP双工持续通信服务端


5.8 TCP双工持续通信客户端


一,网络编程基本概念

1,什么是IP地址?


IP是Internet Protocol Address


,即






互联网协议地址






。互联网之间的通信相当于快递收发,需要知道每个电脑的详细地址才能实现数据的准确收发。



IP地址用来标识网络中的一个通信实体的地址。通信实体可以是计算机、 路由器等



IP地址实际上是一个


32


位整数(称为


IPv4


),以字符串表示的


IP


地址如

192.168.0.1

实际上是把


32


位整数按


8


位分组后的数字表示,目的是便于阅读。


2,IP地址的分类



2.1 公有地址



公有地址(Public address)





Inter NIC





Internet Network Information Center互联网信息中心)负责。这些


IP


地址分配给注册并向Inter NIC


提出申请的组织机构。通过它直接访问互联网。



2.2 私有地址



私有地址(Private address


)属于非注册地址,专门为组织机构内部使用。

3,本地服务器IP地址


127.0.0.1本机地址。192.168.0.0–192.168.255.255为私有地址,属于非注册地址,专门为组织机构内部使用。


4,Windows下常用的ip命令



windows下,我们可以通过命令 ipconfig 获取网卡信息。(Linux 和Mac,是 ifconfig ),通过 ping 查看网络连接:
1,ping www.baidu.com 查看是否能上公网
2,ping 192.168.1.100 查看是否和该计算机在同一个局域网
3,ping 127.0.0.1 查看本机网卡是否可用

5,什么是子网?子网掩码?

子网就是一个网中一个比较低级的网。子网掩码用来确定一个子网中的IP地址及数量,一个子网节点IP地址与子网掩码相与运算得到该子网下的IP地址。一般的子网掩码为255.255.255.0。通过子网掩码确定两个IP地址是否属于同一个子网。

6,什么是网关?

网络关卡口的简称。他的作用就是:链接两个不同的网络,比如联通公司给你家装了宽带(相当于给你家装了一个网关),你家里的所有设备都是在一个局域子网中,这个局域网和互联网之间使用网关进行连接。

7,什么是交换机?

交换机的作用就是分发数据,为设备提供IP地址。交换机直接与设备的网卡连接,数据通过指定的端口发送到指定的设备上,交换机只关心与其联系的设备的mac地址。

8,什么是路由器?

路由器具备WAN口和多个LAN口。它实际上是

网关和交换机的结合体。

wan口与宽带公司机房相连,LAN口与局域网设备相连。

9,什么是路由?

数据从一台电脑发送到另一台电脑的时所走过的路线就叫做路由。

10,子网下的设备如何访问互联网?

通过网关设备里面的NAT技术,即网络地址转换技术。

11,什么是端口?

同一台设备下有很多的应用程序,但是网卡只有一个,数据通过网卡获得和发送,如何确定接收的数据到底是哪一个程序的呢?发给QQ的数据不可能被微信接收。利用端口可以解决这个问题。



11.1 端口分配



端口是虚拟的概念,并不是说在主机上真的有若干个端口。通过端口,可以在一个主机上运行多个网络应用程序。 端口的表示是一个16位的二进制整数,对应十进制的


0-65535


。 操作系统中一共提供了0~65535


可用端口范围。 按端口号分类:



11.2 公认端口(




Well Known Ports




):








0





1023


,它们紧密绑定(binding


)于一些服务。通常这些端口的通讯明确表明了某种服务的协议。例如:80


端口实际上总是


HTTP


通讯。


11.3

注册端口(




Registered Ports




):



从1024





65535


。它们松散地绑 定于一些服务。也就是说有许多服务绑定于这些端口,这些端口同用于许多其它目的。例如:许多系统处理动态端口从1024


左右开始。

二,网络通信协议

1,一张神图

2,OSI网络协议七层模型


OSI模型制定的七层标准模型,分别是:应用层, 表示层,会话层,传输层,网络层,数据链路层,物理层。

3,TCP/IP协议模型


虽然国际标准化组织制定了这样一个网络通信协议的模型,但是实际上互联网通讯使用最多的网络通信协议是TCP/IP


网络通信协议。 TCP/IP 是一个协议族,也是按照层次划分,共四层:应用层,传输层,互连网络层,网络接口层(物理+


数据链路层)。

与OSI模型的区别如下:

4,TCP和UDP的区别?


TCP 和


UDP


的优缺点无法简单地、绝对地去做比较:


TCP


用于在传输层有必要实现可靠传输的情况;UDP


主要用于那些对高速传输 和实时性有较高要求的通信或广播通信。TCP





UDP


应该根据应用的目的按需使用。主要在于他们传输数据的形式不同。

4.1 TCP


TCP(


Transmission Control Protocol


,传输控制协议)。


TCP


方 式就类似于拨打电话,使用该种方式进行网络通讯时,需要建立专门的虚拟连接,然后进行可靠的数据传输,如果数据发送失败,则客户端会自动重发该数据。


4.2 UDP


UDP(User Data Protocol


,用户数据报协议),UDP是一个非连接的协议,传输数据之前源端和终端不建立连接,当它想传送时就简单地去抓取来自应用程序的数据,并尽可能快地把它扔到网络上。 在发送端,UDP


传送数据的速度仅仅是受应用程序生成数据的速度、计算机的能力和传输带宽的限制; 在接收端, UDP把每个消息段放在队列中,应用程序每次从队列中读一个消息段。


UDP方式就类似于发送短信

,使用这种方式进行网络通讯时,不需 要建立专门的虚拟连接,传输也不是很可靠,如果发送失败则客户 端无法获得。UDP 因为没有拥塞控制,一直会以恒定的速度发送数据。即使网络 条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网 络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP


而不是


TCP

4.3 TCP和UDP区别


这两种传输方式都在实际的网络编程中使用,重要的数据一般使用 TCP方式进行数据传输,而大量的非核心数据则可以通过


UDP


方式 进行传递,在一些程序中甚至结合使用这两种方式进行数据传递。 由于TCP


需要建立专用的虚拟连接以及确认传输是否正确,所以使 用TCP


方式的速度稍微慢一些,而且传输时产生的数据量要比


UDP稍微大一些。

5,TCP建立链接的三次握手


TCP是面向连接的协议,也就是说,在收发数据前,必须和对方建 立可靠的连接。 一个TCP


连接必须要经过三次





对话





才能建立起 来,其中的过程非常复杂,只简单的描述下这三次对话的简单过程:

1)主机


A


向主机


B


发出连接请求:





我想给你发数据,可以吗?





,这是第一次对话;

2)主机


B


向主机


A


发送同意连接和要求同步 (同步就是两台主机一个在发送,一个在接收,协调工作)的数据包 :“


可以,你什么时候发?”


,这是第二次对话;

3)主机


A


再发出一个数据包确认主机


B


的要求同步:





我现在就发, 你接着吧!”


, 这是第三次握手。

三次“


对话





的目的是使数据包的发送和接收同步, 经过三次





对话


” 之后,主机A


才向主机


B


正式发送数据。

三次握手建立TCP连接时的状态。


第一步,客户端发送一个包含SYN


即同步(


Synchronize


)标志的


TCP


报文,


SYN


同步报文会指明客户端使用的端口以及TCP


连接的初始序号。

第二步,服务器在收到客户端的SYN


报文后,将返回一个


SYN+ACK


的报文,表示客户端的请求被接受,同时TCP


序号被加一,


ACK


即确认(


Acknowledgement




第三步,客户端也返回一个确认报文ACK


给服务器端,同样


TCP


序列号被加一,到此一个


TCP


连接完成。然后才开始通信的第二步:数据处理。

6,


TCP




断开连接的四次挥手



第一次: 当主机A完成数据传输后


,


将控制位


FIN





1


,提出停止


TCP 连接的请求 ;


第二次: 主机B收到FIN


后对其作出响应,确认这一方向上的


TCP


连接将关闭,





ACK





1




第三次: 由B 端再提出反方向的关闭请求,





FIN





1




第四次: 主机A对主机B


的请求进行确认,将


ACK





1


,双方向的关闭结束




由TCP的三次握手和四次断开可以看出,TCP


使用面向连接的通信方 式, 大大提高了数据通信的可靠性,使发送数据端和接收端在数据 正式传输前就有了交互, 为数据正式传输打下了可靠的基础。

7,


数据包与处理流程


7.1 什么是数据包?


通信传输中的数据单位,一般也称“


数据包





。在数据包中包括: 包、帧、数据包、段、消息。


网络中传输的数据包由两部分组成:一部分是协议所要用到的首 部,另一部分是上一层传过来的数据。首部的结构由协议的具体规 范详细定义。在数据包的首部,明确标明了协议应该如何读取数 据。反过来说,看到首部,也就能够了解该协议必要的信息以及所 要处理的数据。包首部就像协议的脸。

7.2


数据包处理流程





详细流程如下图。

三,socket套接字编程

1,什么是套接字编程?


TCP协议和


UDP


协议是传输层的两种协议。


Socket


是传输层供给应用层的编程接口,所以Socket


编程就分为


TCP


编程和


UDP


编程两类。


Socket编程封装了常见的TCP





UDP


操作,可以实现非常方便的网络编程。

2,socket()函数介绍


在Python


语言标准库中,通过使用


socket


模块提供的


socket


对象,可以在计算机网络中建立可以互相通信的服务器与客户端。在服务器端需要建立一个socket


对象,并等待客户端的连接。客户端使用socket对象与服务器端进行连接,一旦连接成功,客户端和服务器端就可以进行通信了。

注意:

我们可以看出socket


通讯中,发送和接收数据,都 是通过操作系统控制网卡来进行。因此,我们在使用之后,必须关闭socket




socket语法格式如下:


socket.socket([family[, type[, proto]]])

family的参数值有:

AF_UNIX


或者


AF_INET





AF 表示


ADDRESS FAMILY


地址族,AF_INET(又称


PF_INET


)是


IPv4


网络协议的套接字类型;而AF_UNIX 则是


Unix


系统本地通信。


type的参数值有:


type


:


套接字类型可以根据是面向连接的还是非连接分为


SOCK_STREAM





SOCK_DGRAM






protocol


:


一般不填,默认为


0




Socket主要分为面向连接的Socket和无连接的


Socket


。 无连接Socket


的主要协议是用户数据报协议,也就是常说的


UDP


, UDP Socket的名字是


SOCK_DGRAM


。创建套接字


UDP/IP


套接字,可以 调用


socket.socket()


。示例代码如下:


udpSocket=socket.socket(AF_INET,SOCK_DGRAM)

3,socket对象的方法一览

4,UDP编程实例

4.1 单工最简案例


UDP协议时,不需要建立连接,只需要知道对方的


IP


地址和端口号,就可以直接发数据包。但是,能不能到达就不知道了。虽然用UDP传输数据不可靠,但它的优点是和


TCP


比,速度快,对于不要 求可靠到达的数据,就可以使用UDP


协议。 创建Socket


时,


SOCK_DGRAM


指定了这个


Socket


的类型是


UDP


。绑定 端口和TCP


一样,但是不需要调用


listen()


方法,而是直接接收来自任何客户端的数据。


recvfrom()


方法返回数据和客户端的地址与端口,这样,服务器收到数据后,直接调用


sendto()


就可以把数据用


UDP


发给客户端。

udp服务端:
from socket import *

# 最简化的UDP服务端代码
s = socket(AF_INET, SOCK_DGRAM)  # 创建UDP类型的套接字对象
s.bind(("127.0.0.1", 8888))  # 绑定端口,ip可以不写
print("等待接收数据!")
recv_data = s.recvfrom(1024)  # 1024表示本次接收的最大字节数
print(f"收到远程信息:{recv_data[0].decode('gbk')},from {recv_data[1]}")

s.close()

udp客户端:

from socket import *

# 最简化的UDP客户端发送消息代码
s = socket(AF_INET, SOCK_DGRAM)  # 创建UDP类型的套接字
server_addr = ("127.0.0.1", 8888)
data = input("请输入:")
s.sendto(data.encode("gbk"), server_addr)
s.close()

4.2 单工持续通信

udp服务端:

from socket import *

# 持续通信
s = socket(AF_INET, SOCK_DGRAM)  # 创建UDP类型的套接字
s.bind(("127.0.0.1", 8888))  # 绑定端口,ip可以不写
print("等待接收数据!")
while True:
    recv_data = s.recvfrom(1024)  # 1024表示本次接收的最大字节数,recvfrom一直监听知道由数据被接受
    recv_content = recv_data[0].decode('gbk')
    print(f"收到远程信息:{recv_content},from {recv_data[1]}")
    if recv_content == "exit":
        print("结束聊天!")
        break

s.close()

udp客户端:

from socket import *

# UDP客户端持续发送消息代码
s = socket(AF_INET, SOCK_DGRAM)  # 创建UDP类型的套接字
addr = ("127.0.0.1", 8888)

while True:
    data = input("请输入:")
    s.sendto(data.encode("gbk"), addr)
    if data == "exit":
        print("结束聊天!")
        break

s.close()

4.3 双工持续通信

使用本地主机,开启两个接收和发送两个线程,实现双工通信。

udp服务端:

from socket import *
from threading import Thread


def recv_data():
    while True:
        recv_data = s.recvfrom(1024)  # 1024表示本次接收的最大字节数
        recv_content = recv_data[0].decode('gbk')
        print(f"收到远程信息:{recv_content},from {recv_data[1]}")
        if recv_content == "exit":
            print("结束聊天!")
            break


def send_data():
    addr = ("127.0.0.1", 9999)
    while True:
        data = input("请输入:")
        s.sendto(data.encode("gbk"), addr)
        if data == "exit":
            print("结束聊天!")
            break


if __name__ == '__main__':
    s = socket(AF_INET, SOCK_DGRAM)  # 创建UDP类型的套接字
    s.bind(("127.0.0.1", 8888))  # 绑定端口,ip可以不写
    # 创建两个线程
    t1 = Thread(target=recv_data)
    t2 = Thread(target=send_data)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

udp客户端:

from socket import *
from threading import Thread


def recv_data():
    while True:
        recv_data = s.recvfrom(1024)  # 1024表示本次接收的最大字节数
        recv_content = recv_data[0].decode('gbk')
        print(f"收到远程信息:{recv_content},from {recv_data[1]}")
        if recv_content == "exit":
            print("结束聊天!")
            break


def send_data():
    addr = ("127.0.0.1", 8888)
    while True:
        data = input("请输入:")
        s.sendto(data.encode("gbk"), addr)
        if data == "exit":
            print("结束聊天!")
            break


if __name__ == '__main__':
    s = socket(AF_INET, SOCK_DGRAM)  # 创建UDP类型的套接字
    s.bind(("127.0.0.1", 9999))  # 绑定端口,ip可以不写
    # 创建两个线程
    t1 = Thread(target=recv_data)
    t2 = Thread(target=send_data)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

5,TCP/IP编程实例

5.1 TCP/IP编程简介


面向连接的Socket


使用的协议是


TCP


协议。


TCP





Socket


名称是


SOCK_STREAM


。创建套接字


TCP


套接字,可以调用


socket.socket()


。示例代码如下:

 tcpSocket=socket.socket(AF_INET,SOCK_STREAM)



5.2 TCP




编程的实现过程



在Python


语言中创建


Socket


服务端程序,需要使用


socket


模块中的socket类。创建


Socket


服务器程序的步骤如下:

(1) 创建


Socket


对象。

(2) 绑定端口号。

(3) 监听端口号。

(4) 等待客户端Socket


的连接。

(5) 读取客户端发送过来的数据。

(6) 向客户端发送数据。

(7) 关闭客户端Socket


连接。

(8) 关闭服务端Socket


连接。


5.3 TCP单工通信服务端

from socket import *

server_socket = socket(AF_INET,SOCK_STREAM) #建立TCP套接字
server_socket.bind(("127.0.0.1",8899))  #本机监听8899端口
server_socket.listen(5)
print("等待接收连接!")
client_socket,client_info = server_socket.accept()
recv_data = client_socket.recv(1024)  #最大接收1024字节
print(f"收到信息:{recv_data.decode('gbk')},来自:{client_info}")

client_socket.close()
server_socket.close()


5.4 TCP单工通信客户端

from socket import *

client_socket = socket(AF_INET,SOCK_STREAM)
client_socket.connect(("127.0.0.1",8899))

client_socket.send("hello".encode("gbk"))
client_socket.close()
#注意:
# 1. tcp客户端已经链接好了服务器,所以在以后的数据发送中,不需要填写对方的ip和port----->打电话
# 2. udp在发送数据的时候,因为没有之前的链接,所以需要在每次的发送中,都要填写接收方的ip和port--->写信

5.5 TCP单工持续通信服务端

from socket import *

server_socket = socket(AF_INET,SOCK_STREAM) #建立TCP套接字
server_socket.bind(("127.0.0.1",8899))  #本机监听8899端口
server_socket.listen(5)
print("等待接收连接!")
client_socket,client_info = server_socket.accept()
print("一个客户端建立连接成功!")
while True:
    recv_data = client_socket.recv(1024)  #最大接收1024字节
    recv_content = recv_data.decode('gbk')
    print(f"客户端说:{recv_content},来自:{client_info}")
    if recv_content == "end":
        break
    msg = input(">")
    client_socket.send(msg.encode("gbk"))

client_socket.close()
server_socket.close()

5.6 TCP单工持续通信客户端

from socket import *

client_socket = socket(AF_INET,SOCK_STREAM)
client_socket.connect(("127.0.0.1",8899))
while True:
    #给服务端发消息
    msg = input(">")
    client_socket.send(msg.encode("gbk"))
    if msg =="end":
        break
    #接收服务器端数据
    recv_data = client_socket.recv(1024) #最大接收1024字节
    print(f"服务器端说:{recv_data.decode('gbk')}")

client_socket.close()

5.7 TCP双工持续通信服务端

from socket import *
from threading import Thread


def recv_data():
    while True:
        recv_data = client_socket.recv(1024)  # 最大接收1024字节
        recv_content = recv_data.decode("gbk")
        print(f"客户端说:{recv_content},来自:{client_info}")
        if recv_content == "end":
            print("结束接收消息!")
            break

def send_data():
    while True:
        msg = input(">")
        client_socket.send(msg.encode("gbk"))
        if msg == "end":
            print("结束发送消息!")
            break

if __name__ == '__main__':
    server_socket = socket(AF_INET, SOCK_STREAM)  # 建立TCP套接字
    server_socket.bind(("127.0.0.1", 8899))  # 本机监听8899端口
    server_socket.listen(5)
    print("等待接收连接!")
    client_socket, client_info = server_socket.accept()
    print("一个客户端建立连接成功!")

    t1 = Thread(target=recv_data)
    t2 = Thread(target=send_data)
    t1.start()
    t2.start()

    t1.join()
    t2.join()

    client_socket.close()
    server_socket.close()

5.8 TCP双工持续通信客户端

from socket import *
from threading import Thread


def recv_data():
    while True:
        # 接收服务器端数据
        recv_data = client_socket.recv(1024)  # 最大接收1024字节
        recv_content = recv_data.decode('gbk')
        print(f"服务器端说:{recv_content}")
        if recv_content == "end":
            print("结束接收消息")
            break

def send_data():
    while True:
        # 给服务端发消息
        msg = input(">")
        client_socket.send(msg.encode("gbk"))
        if msg == "end":
            break

if __name__ == '__main__':
    client_socket = socket(AF_INET, SOCK_STREAM)
    client_socket.connect(("127.0.0.1", 8899))

    t1 = Thread(target=recv_data)
    t2 = Thread(target=send_data)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    client_socket.close()



版权声明:本文为weixin_44992737原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。