【python】网络编程

本文介绍了网络中的IP地址概念,包括IPv4和IPv6的表示方式,以及如何在Linux和Windows上查看IP。接着讨论了端口的作用和分类,以及TCP协议的特性,如面向连接、可靠传输。文章还详细讲解了如何使用Python进行TCPsocket编程,包括客户端和服务器的开发,并涉及字符串编码与解码。最后提到了多路复用服务器和协程的概念,以及gevent库在实现协程中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【Python】网络

IP地址

IP地址就是表示网络中设备的一个地址

IP的表现形式
  • IPV4 点分十进制形式
  • IPV6 冒号十六进制组成
查看IP地址
  • Linux使用ifconfig命令
  • Windows使用ipconfig命令
查看网络是否能够运行

ping ip

C:\Users\hp>ping baidu.com

正在 Ping baidu.com [110.242.68.66] 具有 32 字节的数据:
来自 110.242.68.66 的回复: 字节=32 时间=20ms TTL=53
来自 110.242.68.66 的回复: 字节=32 时间=29ms TTL=53
来自 110.242.68.66 的回复: 字节=32 时间=21ms TTL=53
来自 110.242.68.66 的回复: 字节=32 时间=21ms TTL=53

110.242.68.66 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 20ms,最长 = 29ms,平均 = 22ms
  • 检查本地是否能够通信
ping 127.0.0.1
  • 域名 是ip地址的别名

端口

是数据传输的通道,是数据传输的必经之路

分类

一共是65532个端口号

  • 知名端口号(0~1023)
  • 动态端口号(1024~65532)

ip + 端口号 可以确定唯一的应用成功程序

TCP

概念

是一种面向链接的,可靠的,基于数据流的传输层协议

TCP通信步骤
  • 创建连接
  • 传输数据
  • 关闭连接
TCP的特点

1.面向连接

2.可靠传输

  • TCP采用发送应答机制
  • 超时重传
  • 错误校验
  • 流量控制

socket

套接字,是进程之间通信的工具。

TCP客户端程序开发

程序架构:
	B/S: (浏览器/服务器)
    C/S: (客户端/服务器) 使用某个服务,必须下载对应的客户端软件
客户端开发流程
  • 创建对象
  • 建立连接
  • 发送信息
  • 接受信息
  • 关闭链接
再python中使用socket,要导入socket模块
1.创建socket对象(socket.socket())
2.建立链接(socket对象.connect())
3.发送信息(socket对象.send())
4.接收信息(socket对象.resv())
5.关闭链接(socket对象.close())
ptyhon中的字符串
python中的字符串分两种类型
str:
byte:字节,二进制,网络传输的基本单位
str-->bytesstr.encode(编码类型)
bytes --> str bytes.decode(编码类型)

gbk 将中文编码成2个字节
utf-8 将中文编码成3个字节
客户端开发代码示例
    # 创建对象
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)  # 固定写法
    # 和服务器建立链接
    sock.connect(('127.0.0.1', 8080))  # 元组类型,ip + 端口号
    print('链接成功')
    # 发送数据
    send_message = 'hello'
    sock.send(send_message.encode())  # 发送信息
    # 接受数据
    buffer = sock.recv(1024)  # 一次接受多少字节数据 # 如果对方没有发送数据,会出现阻塞式等待
    print(buffer.decode())
    # 关闭数据
    sock.close()

服务器开发

  • 创建socket对象
  • bind服务器ip + 端口
  • listen监听套接字,将注定套接字变为被动套接字,可以接受客户端链接
    • 主动套接字:可以接受发送信息的套接字
    • 被动套接字:不能收发信息
  • accept 阻塞等待客户端的链接
  • 有客户端的链接,就会返回一个新的socket,用来和客户端通信
    • 新的socket关闭,表示不能通信
    • 监听的socket关闭了,不能接受新的客户端链接

特殊情况下:启动服务器的时候,运行一次,马上关闭再次运行,就会出现地址已经被使用了这个bug,端口需要等待30s-2min才可以再次使用

解决方案:

  • 换个端口
  • 代码解决,端口复用
    listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True) # 端口复用
    #                      设置级别          设置什么内容(权限)   设置什么值? True
    # listen_sock.bind(('127.0.0.1', 8080))
    listen_sock.bind(('', 8080))  # 绑定服务器中的任意一个网卡
    # 设置监听,参数表示:未accept时,最大的可待连接数
    listen_sock.listen(5)
    # 等待客户端链接,返回一个元组 socket + (ip + port)
    sock, ip_port = listen_sock.accept()
    print(f'客户端{ip_port}连接了')
    # 接受信息
    buff = sock.recv(1024)
    print(buff.decode())
    # 发送信息
    send_message = '信息已接受'
    sock.send(send_message.encode())
    # 关闭链接
    sock.close()
    listen_sock.close()
判断客户端断开

使用recv的返回值判断,当对方的sock关闭后,sock就不会阻塞了,recv接受的内容是空字符串,长度为0

 buff = sock.recv(1024)
    if buff:
        print(buff.decode())
    else:
        print('客户端已关闭')

多路版本的服务器

import socket
import threading


def handle_request(sock, ip_port):
    while True:
        # 接收信息
        buff = sock.recv(1024)
        if buff:
            print(f'解说的信息是:{buff.decode()}')
            send_message = '信息已收到'.encode()
            sock.send(send_message)
        else:
            print(f'客户端{ip_port}已经下线...')
            break
    sock.close()


if __name__ == '__main__':
    listen_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    listen_sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, True)
    listen_sock.bind(('', 8080))
    listen_sock.listen(5)
    print('等待链接中...')
    while True:
        sock, ip_port = listen_sock.accept()
        print(f'客户端{ip_port}已上线。。。')
        # 创建线程执行任务
        handle = threading.Thread(target=handle_request, args=(sock, ip_port))
        handle.start()
    listen_sock.close()
'''
等待链接中...
客户端('127.0.0.1', 52784)已上线。。。
解说的信息是:hello
客户端('127.0.0.1', 52784)已经下线...
'''

协程

实现多任务的方式,比线程占用资源更小

方法
import gevent
# pip install gevent
import gevent


def sing(singer, song):
    for i in range(5):
        print(f'{singer} is singing {song}')
        # gevent遇到阻塞式等待会切换携程
        gevent.sleep(0.1)  # 切换携程


def dance(dancer, name):
    for i in range(5):
        print(f'{name} {dancer} is dancing')
        gevent.sleep(0.1)


if __name__ == '__main__':
    # 创建协程对象
    g1 = gevent.spawn(sing, '张三', '阿山')
    g2 = gevent.spawn(dance, '花花', '阿山')

    # 阻塞式等待
    g1.join() # 没有阻塞就不会切换,就会直接结束
    g2.join()

'''
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
'''
猴子补丁

gevent不会识别time.sleep(),可以使用猴子补丁的方式 ,将time.sleep()转化为gevent.sleep()

import gevent
import time
from gevent import monkey

monkey.patch_all()  # 使用gevent中的模块替换系统中的模块


def sing(singer, song):
    for i in range(5):
        print(f'{singer} is singing {song}')
        # gevent遇到阻塞式等待会切换携程
        # gevent.sleep(0.1)  # 切换携程
        time.sleep(0.1)


def dance(dancer, name):
    for i in range(5):
        print(f'{name} {dancer} is dancing')
        # gevent.sleep(0.1)
        time.sleep(0.1)


if __name__ == '__main__':
    # 创建协程对象
    g1 = gevent.spawn(sing, '张三', '阿山')
    g2 = gevent.spawn(dance, '花花', '阿山')

    # 阻塞式等待
    g1.join()  # 没有阻塞就不会切换,就会直接结束
    g2.join()
'''
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
张三 is singing 阿山
阿山 花花 is dancing
'''
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值