2024年最新Python网络编程(小白一看就懂)

3.1.1 理论

应用层:python代码,b’hello’

传输层:预备如何传输、使用的端口,b’发送者的端口+hello+接受者的端口’

网络层:ip,b’发送者的ip+发送者的端口+hello+接受者的端口+接受者的端口’

数据链路层:mac,b’发送者mac地址+发送者的ip+发送者的端口+hello+接受者的端口+接受者的端口+接受者mac地址’

物理层:转化成电信号,通过网线传输

3.1.2 每层涉及到的协议和物理设备

第五层 应用层:python代码。

第四层 传输层:port,udp,tcp。四层路由器,四层交换机。

第三层 网络层:ipv4和ipv6。路由器,三层交换机。(家里的路由器带有交换机功能)

第二层 数据链路层:mac,arp协议。网卡,二层交换机。

第一层 物理层:网线。

3.2 tcp协议和udp协议
3.2.1 tcp协议

tcp(语音聊天)- 线下缓存高清电影、qq远程控制、发邮件

需要先建立连接,然后才能通信的。

特点:占用连接、可靠(消息不会丢失)、实时性高、慢

建立连接:指三次握手

断开连接:指四次挥手

3.2.2 udp协议

udp(发短信)- 在线播放视频、qq发消息、微信发消息

不需要建立连接,就可以通信的。

特点:不占用连接、不可靠(消息可能因为网络不稳定而丢失)、快

四、tcp协议的代码

操作系统会统一分配计算机的所有资源

socket():tcp协议的server

socket(type=socket.SOCK_DGRAM):udp协议的server【udp协议中使用】

bind:绑定一个id和端口

listen:监听,代表socket服务的开启

accept:等到有客户端来访问,与客户端建立连接

send:直接通过连接发送消息,不需要写地址

sendto:需要写一个对方的地址【udp协议中使用】

recv:只接收消息

recvfrom:接收消息和地址【udp协议中使用】

connect:客户端/tcp协议的方法,和server端建立连接

close:关闭服务(sk.close)/连接(conn.close)

4.1 能够接收多个客户端的请求

server.py

import socket

sk = socket.socket()
sk.bind(('127.0.0.1', 9000))  # 申请操作系统的资源
sk.listen()

while True:
    # print(f'sk:{sk}')
    # conn里存储的是一个客户端和服务端的连接信息
    conn, adder = sk.accept()  # 能够和多个客户端进行握手了
    # print(f'conn:{conn}')
    conn.send(b'hello')
    msg = conn.recv(1024)
    print(msg)
    conn.close()  # 挥手,断开连接

sk.close()  # 归还申请的操作系统的资源


client.py

import socket

sk = socket.socket()

# 必须和server端的一致
sk.connect(('127.0.0.1', 9000))
msg = sk.recv(1024)
print(msg)

# 客户端 发送 消息给服务端
sk.send(b'bye')

sk.close()


4.2 在连接内,和客户端多说几句。以及解决不能传输中文问题

server.py

import socket

sk = socket.socket()
sk.bind(('127.0.0.1', 9000))  # 申请操作系统的资源
sk.listen()

while True:  # 为了和多个客户端进行握手
    # conn里存储的是一个客户端和服务端的连接信息
    conn, adder = sk.accept()  # 能够和多个客户端进行握手了

    while True:
        send_msg = input('please input you want say:')

        conn.send(send_msg.encode('utf-8'))
        if send_msg.upper() == 'Q':
            break
        msg = conn.recv(1024).decode('utf-8')
        if msg.upper() == 'Q':
            break
        print(msg)
    conn.close()  # 挥手,断开连接

sk.close()



client.py

import socket

sk = socket.socket()

sk.connect(('127.0.0.1', 9000))

while True:
    msg = sk.recv(1024).decode('utf-8')
    if msg.upper() == 'Q':
        break
    print(msg)

    send_msg = input('please input you want say:')
    sk.send(send_msg.encode('utf-8'))
    if send_msg.upper() == 'Q':
        break

sk.close()



4.3 程序执行到哪里会阻塞,什么时候结束阻塞
input() 等待,直到用户输入enter键

accept() 阻塞,有客户端来与我建立完连接之后

recv() 阻塞,直到收到对方发过来的消息之后

recvfrom() 阻塞,直到收到对方发过来的消息之后

connect() 阻塞,直到server端结束了对一个client的服务,开始和当前client建立连接的时候


五、udp协议的代码

server.py

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)  # 表示一个udp协议
sk.bind(('127.0.0.1', 9000))

# 服务端不能先发送消息,因为服务端不知道客户端的ip
while True:
    msg, addr = sk.recvfrom(1024)
    print(msg.decode('utf-8'))
    send_msg = input('please input you want say:')
    sk.sendto(send_msg.encode('utf-8'), addr)
# server端不需要判断退出
# 因为不和这个客户端通信,还要和其他客户端通信



client.py

import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
server = ('127.0.0.1', 9000)

while True:
    send_msg = input('please input you want say:')
    if send_msg.upper() == 'Q':
        break
    sk.sendto(send_msg.encode('utf-8'), server)
    msg = sk.recv(1024).decode('utf-8')
    if msg.upper() == 'Q':
        break
    print(msg)



六、粘包问题
6.1 tcp协议中的粘包现象

两条或更多条分开发送的信息连在一起就是粘包现象

server.py
import socket

sk = socket.socket()
sk.bind(('127.0.0.1', 9001))
sk.listen()

conn, addr = sk.accept()
conn.send(b'hello')
conn.send(b'nice')
conn.close()
sk.close()




client.py
import time
import socket

sk = socket.socket()
sk.connect(('127.0.0.1', 9001))

time.sleep(0.1)
msg1 = sk.recv(1024)
print(msg1)
msg2 = sk.recv(1024)
print(msg2)

sk.close()



先启动server,然后启动client,client打印结果如下:

b'hellonice'
b''


产生了粘包现象,去掉睡眠时间结果如下:

b'hellonice'
b'nice'


【注意】即使不设置睡眠时间,也有几率粘包

6.2 产生粘包现象的两个原因

粘包现象只出现在tcp协议中,因为tcp协议中,多条消息之间没有边界(流式传输),并且还有一大堆优化算法。

  • 发送端:两条消息很短,并且发送的间隔时间也很短,由于优化机制就合并在一起发送了
  • 接收端:多条消息由于没有及时接收,在接收方的缓存中堆在一起而导致的粘包
6.3 粘包发生的本质

tcp协议的传输是流式传输,数据与数据之间没有边界

6.4 解决粘包的问题的本质

设置边界

6.5 解决粘包

自定义协议

服务端:先发送4个字节的数据长度,再按照长度发送数据

客户端:先接收4个字节,知道数据的长度,再按照长度接收数据

6.6 struct模块

该模块可以把一个类型,如数字,转成固定长度的 bytes。

数字的范围 -2**31-1 ~ 2**31,共 2**32 个数字。pack可以把这个范围内的任意一个数字转为长度为 4 的字节。

import struct

num1 = 123456789
num2 = 12345
num3 = 123

ret1 = struct.pack('i', num1)
print(ret1, len(ret1))  # b'\x15\xcd[\x07' 4
ret2 = struct.pack('i', num2)
print(ret2, len(ret2))  # b'90\x00\x00' 4
ret3 = struct.pack('i', num3)
print(ret3, len(ret3))  # b'{\x00\x00\x00' 4

print(struct.unpack('i', ret1))  # (123456789,)
print(struct.unpack('i', ret2))  # (12345,)
print(struct.unpack('i', ret3))  # (123,)



6.7 解决粘包代码
server.py
import socket
import struct

sk = socket.socket()
sk.bind(('127.0.0.1', 9001))
sk.listen()

conn, addr = sk.accept()
msg1 = input('>>>')
msg2 = input('>>>')
blen = struct.pack('i', len(msg1.encode()))
conn.send(blen)
conn.send(msg1.encode())
conn.send(msg2.encode())
conn.close()
sk.close()



client.py
import time
import socket
import struct

sk = socket.socket()
sk.connect(('127.0.0.1', 9001))

time.sleep(0.1)
length = sk.recv(4)
length = struct.unpack('i', length)[0]
msg1 = sk.recv(length)
msg2 = sk.recv(1024)

print(msg1.decode('utf-8'))
print(msg2.decode('utf-8'))

sk.close()



6.8 总结
  1. recv(1024)不代表一定收到1024个字节,而是最多只能收1024个字节
  2. 两条连续发送的数据一定要避免粘包问题
  3. tcp协议的自定义协议解决粘包问题的思路:先发送数据的长度,再发送数据。【将发送的数据组成json格式:先发送json的长度,再发json(json中存了接下来要发送的数据长度),再发数据】
七、基于udp协议的多人聊天
7.1 基于udp协议的多人聊天

自动识别用户,不能使用 ip 和 port

server.py
import socket

friend_lst = {'jack': '31', 'tom': '34'}
sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(('127.0.0.1', 9000))
while 1:
    msg, addr = sk.recvfrom(1024)
    msg = msg.decode('utf-8')
    name, message = msg.split('|')
    print(f'\033[1;{friend_lst.get(name,"30")}m {name}:{message} \033[0m')
    content = input('>>>')
    sk.sendto(content.encode('utf-8'), addr)



client.py
import socket

name = 'jack'
sk = socket.socket(type=socket.SOCK_DGRAM)

while 1:
    content = input('>>>')
    if content.upper() == 'Q':
        break
    content = f'{name}|{content}'
    sk.sendto(content.encode('utf-8'), ('127.0.0.1', 9000))
    msg = sk.recv(1024).decode('utf-8')
    if msg.upper() == 'Q':
        break
    print(msg)



八、基于tcp协议的文件传输
server.py
import socket
import json
# 接收
sk = socket.socket()
sk.bind(('127.0.0.1', 9002))
sk.listen()
conn, addr = sk.accept()
msg = conn.recv(1024).decode('utf-8')
msg = json.loads(msg)

with open(msg['filename'], 'wb') as f:
    content = conn.recv(msg['filesize'])
    print('-->', len(content))
    f.write(content)

print(msg)
conn.close()
sk.close()



client.py
import os
import json
import socket

# 发送
sk = socket.socket()
sk.connect(('127.0.0.1', 9002))

# 文件名、文件大小
abs_path = r'E:\A.PythonProject\action\day30\作业\a.txt'
filename = os.path.basename(abs_path)
filesize = os.path.getsize(abs_path)
dic = {'filename': filename, 'filesize': filesize}
str_dic = json.dumps(dic)
sk.send(str_dic.encode('utf-8'))

with open(abs_path, 'rb') as f:
    content = f.read()
    sk.send(content)
sk.close()



8.1 优化

上面代码存在的问题:发送的字典可能和文件内容发送粘包;发送大文件时,接收的文件大小比原来的小

server.py
import socket
import json
# 接收
import struct

sk = socket.socket()
sk.bind(('127.0.0.1', 9002))
sk.listen()
conn, addr = sk.accept()
msg_len = conn.recv(4)
dic_len = struct.unpack('i', msg_len)[0]


### 最后

Python崛起并且风靡,因为优点多、应用领域广、被大牛们认可。学习 Python 门槛很低,但它的晋级路线很多,通过它你能进入机器学习、数据挖掘、大数据,CS等更加高级的领域。Python可以做网络应用,可以做科学计算,数据分析,可以做网络爬虫,可以做机器学习、自然语言处理、可以写游戏、可以做桌面应用…Python可以做的很多,你需要学好基础,再选择明确的方向。这里给大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

#### 👉Python所有方向的学习路线👈

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

![](https://img-blog.csdnimg.cn/img_convert/604bae65027d4d67fb62410deb210454.png)

#### 👉Python必备开发工具👈

工欲善其事必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

![](https://img-blog.csdnimg.cn/img_convert/fa276175617e0048f79437bd30465479.png)



#### 👉Python全套学习视频👈

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

![](https://img-blog.csdnimg.cn/img_convert/16ac689cb023166b2ffa9c677ac40fc0.png)



#### 👉实战案例👈



学python就与学数学一样,是不能只看书不做题的,直接看步骤和答案会让人误以为自己全都掌握了,但是碰到生题的时候还是会一筹莫展。



因此在学习python的过程中一定要记得多动手写代码,教程只需要看一两遍即可。

![](https://img-blog.csdnimg.cn/img_convert/0d8c31c50236a205928a1d8ae8a0b883.png)



#### 👉大厂面试真题👈

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

![](https://img-blog.csdnimg.cn/img_convert/99461e47e58e503d2bc1dc6f4668534a.png)

**[需要这份系统化学习资料的朋友,可以戳这里无偿获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值