python 网络编程

网络基础

  • mac地址:不会改变的,不会重复的,每个电脑出厂网卡上的序列。能够唯一标识你的机器
  • ip地址:会改变。能够更好更方便的找到你的机器
    • ipv4:四位点分十进制
      • 192.168.0.0    8位的二进制   范围0.0.0.0到255.255.255.255
    • 公网地址:需要自己申请购买的地址
    • 内网地址:保留字段,永不和公网冲突
      • 192.168.0.0——192.168.255.255
      • 172.16.0.0——172.31.255.255
      • 10.0.0.0——10.255.255.255
    • 子网掩码:用来判断两台机器是否在同一个局域网内(用ip和子母掩码做按位与,相同即统一局域网)
    • ipv6:六位的冒分十六进制
      • 0:0:0:0:0:0——FFFFFF:FFFFFF:FFFFFF:FFFFFF:FFFFFF:FFFFFF
    • 端口:确认机器上的具体应用程序的(0-65535)
  • 局域网
    • 在同一个局域网内的机器由交换机负责通信
    • 交换机只认识mac地址
    • 可以完成广播,,单播和组播
    • 多个局域网通信
      • 路由器
        • 需要提供网关ip,同一个局域网的所有机器共享一个网关
        • 不能访问除了本局域网外的其他内网的ip地址 
  • arp协议:地址解析协议,通过一台机器的ip地址获取到它的mac地址。用到了交换机的广播和单播功能

 

网络开发架构

  • C/S架构:需要安装才可使用
    • client:客户端
    • server:服务端
  • B/S架构:需要浏览器
    • browers:浏览器
    • server:服务端

 

osi五层协议

  1. 物理层
  2. 数据链路层          mac  arp协议相关     硬件:网卡  二层交换机
  3. 网络层                 ipv4和ipv6                 硬件:路由器  三层交换机
  4. 传输层                 port                            硬件:四层路由器  四层交换机
  5. 应用层 

 

tcp和udp      

tcp(语音聊天、视频聊天、线下缓存电影、发邮件)

  • 需要先建立连接,然后才能通信
  • 占用连接、可靠(消息不会丢失)、实时性高、慢
  • 建立连接——三次握手(全双工通信)
    • client端向server端发送请求连接SYN
    • server端回复client端SYN+ACK
    • client端再次向server端回复ACK
  • 断开连接——四次挥手
    • 断开连接发送FIN信号(A)
    • 回复ACK信号(B)
    • 发送FIN信号(B)
    • 回复ACK信号(A)

udp(发信息、在线播放)

  • 不需要建立连接,就可以通信
  • 不占用连接、不可靠(消息因网络不稳定丢失)、快

 

tcp

# tcp——server
import socket

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

conn, addr = sk.accept()  # conn存储一个client端和server端的连接信息
conn.send('你好'.encode("utf-8"))

msg = conn.recv(1024)
print(msg)

conn.close()  # 挥手断开连接
sk.close()  # 归还操作系统资源


# tcp——client
import socket

sk = socket.socket()
sk.connect(("127.0.0.1",8080))

msg = sk.recv(1024)
print(msg.decode("utf-8"))

sk.send(b'bye')

sk.close()
# tcp——server 聊天
import socket

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

while True:
    conn, addr = sk.accept()  # conn存储一个client端和server端的连接信息
    while True:
        send_msg = input(">>>")
        conn.send(send_msg.encode("utf-8"))
        if send_msg.upper() == "Q":
            break
        msg = conn.recv(1024)
        print(msg.decode("utf-8"))
    conn.close()  # 挥手断开连接

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

# tcp——client 聊天
import socket

sk = socket.socket()
sk.connect(("127.0.0.1", 8080))

while True:
    msg = sk.recv(1024).decode("utf-8")
    if msg.upper() == "Q":break
    print(msg)
    send_msg = input(">>>")
    sk.send(send_msg.encode("utf-8"))
    if send_msg.upper() == "Q": break

sk.close()

 

udp

# udp——server
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(("127.0.0.1", 8080))
msg, addr = sk.recvfrom(1024)
print(msg)
sk.sendto(b'hello', addr)


# udp——client
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
addr = ("127.0.0.1", 8080)
sk.sendto(b'hi', addr)
msg = sk.recv(1024)
print(msg)
# udp——server 聊天
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
sk.bind(("127.0.0.1", 8080))
while True:
    msg, addr = sk.recvfrom(1024)
    print(msg.decode("utf-8"))
    send_msg = input(">>>").encode("utf-8")
    sk.sendto(send_msg, addr)


# udp——client 聊天
import socket

sk = socket.socket(type=socket.SOCK_DGRAM)
addr = ("127.0.0.1", 8080)
while True:
    send_msg = input(">>>").encode("utf-8")
    if send_msg.upper() == "Q":break
    sk.sendto(send_msg, addr)
    msg = sk.recv(1024).decode("utf-8")
    if msg.upper() == "Q":
        break
    print(msg)

 

粘包——tcp

  • 粘包只出现在tcp协议中,因为tcp协议多条信息之间没有边界,并且还有一大堆优化算法
  • 服务端:两条信息发送间隔很短,信息很短(都在缓存中一起发送过去)
  • 客户端:接收信息不及时(缓存堆积)

# tcp——server    解决粘包问题
import struct
import socket

sk = socket.socket()
sk.bind(("127.0.0.1", 8080))
sk.listen()

conn, addr = sk.accept()
msg1 = input(">>>").encode()
msg2 = input(">>>").encode()

blen = struct.pack("i", len(msg1))      # 将长度信息转换为4字节的byte
conn.send(blen)
conn.send(msg1)
conn.send(msg2)
conn.close()
sk.close()


# tcp——client
import struct
import socket

sk = socket.socket()
sk.connect(('127.0.0.1', 8080))
length = sk.recv(4)                    # 接收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()

 

文件传输

# server
import json
import struct
import socket
# 接收
sk = socket.socket()
sk.bind(('127.0.0.1',9001))
sk.listen()

conn,_ =sk.accept()
msg_len = conn.recv(4)
dic_len = struct.unpack('i',msg_len)[0]
msg = conn.recv(dic_len).decode('utf-8')
msg = json.loads(msg)

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


# client
import os
import json
import struct
import socket
# 发送
sk = socket.socket()
# sk.connect(('192.168.14.109',9012))
sk.connect(('127.0.0.1',9001))

# 文件名\文件大小
abs_path = r'D:\python22期\day28 课上视频\3.网络基础概念.mp4'
filename = os.path.basename(abs_path)
filesize = os.path.getsize(abs_path)
dic = {'filename':filename,'filesize':filesize}
str_dic = json.dumps(dic)
b_dic = str_dic.encode('utf-8')
mlen = struct.pack('i',len(b_dic))
sk.send(mlen)   # 4个字节 表示字典转成字节之后的长度
sk.send(b_dic)  # 具体的字典数据

with open(abs_path,mode = 'rb') as f:
    while filesize>0:
        content = f.read(1024)
        filesize -= len(content)
        sk.send(content)
sk.close()

 

sockerserver

  • 对底层socket的封装
  • 实现tcp的并发
# server
import time
import socketserver


class Myserver(socketserver.BaseRequestHandler):
    def handle(self):
        conn = self.request
        while True:
            try:
                content = conn.recv(1024).decode('utf-8')
                conn.send(content.upper().encode('utf-8'))
                time.sleep(0.5)
            except ConnectionResetError:
                break


server = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), Myserver)
server.serve_forever()


# client
import socket

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

while True:
    sk.send(b'hello')
    content = sk.recv(1024).decode('utf-8')
    print(content)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值