欢迎来到十九分快乐的博客

生死看淡,不服就干。

2.网络编程基本语法

网络编程基本语法

1.TCP基本语法

服务端
# 服务端 (七剑下天山)
"""
注意 :
    一发一收必须成对,否则会出现数据异常
"""
import socket
# 1.建立一个TCP(socket)对象
sk = socket.socket()

# 2.绑定对应的IP和端口号(注册网络,让其他电脑可以访问到该主机)
sk.bind(("127.0.0.1",8000)) #注意:参数为一个元组

# 3.开启监听(监听是否有设备访问) 
sk.listen()

# 4.建立连接 (三次握手)
"""
接收到对象和访问设备的地址:
addr : ('127.0.0.1', 45466)
"""
conn,addr = sk.accept()

# 5.处理收发数据的逻辑
msg = conn.recv(1024) #最多一次接受1024个字节
print(msg.decode("utf-8")) #需要解码成字符串

# 6.断开连接 (四次挥手)
conn.close()

# 7.退还端口
sk.close()
客户端
# 客户端
import socket

# 1.建立一个TCP(socket)对象
sk = socket.socket()

# 2.与服务端建立连接 (需要知道目标主机的IP和端口号)
sk.connect(("127.0.0.1",8000)) #注意: 一个参数元组

# 3.发送数据 (必须是二进制字节流)
strvar = "好人一生平安~"
sk.send(strvar.encode("utf-8"))

# 4.关闭连接
sk.close()

2.TCP循环发消息

服务端
# 循环发消息[服务端]
import socket
sk = socket.socket() #建立TCP对象
sk.bind(("127.0.0.1",8001)) #绑定ip端口注册网络
sk.listen() #开启监听

while True: #服务端永不停机,一直监听
    conn,addr  = sk.accept() #建立连接(三次招手)
    # 循环发消息
    while True:
        msg = conn.recv(1024) #收消息
        print(msg.decode("utf-8"))
        # 接收q停止循环
        if msg == b"q" or msg == b"Q":
            break
        strvar = input("请输入内容:")
        conn.send(strvar.encode("utf-8")) #发消息
        
    conn.close() #关闭连接 (四次挥手)      
    
sk.close() #退还端口
客户端
# 循环发消息[客户端]
import socket

sk = socket.socket() #建立TCP对象
sk.connect(("127.0.0.1",8001)) #与服务端建立连接

# 循环发消息
while True:
    # 发送数据
    strvar = input("请输入您要发送的数据(按q结束):")
    sk.send(strvar.encode()) #
    # 停止循环条件
    if strvar.upper() == "Q":
        break
    # 接收数据
    msg = sk.recv(1024)
    print(msg.decode())
    
sk.close() #关闭连接

3.UDP 基本语法

服务端
# 服务端
import socket

# 1.建立一个UDP对象
sk = socket.socket(type = socket.SOCK_DGRAM)
# 2.绑定IP和端口号
sk.bind(("127.0.0.1",8002)) #参数一个元组
# 3.针对udp服务器,第一次只能接受数据
while True:
    while True:
        msg,addr = sk.recvfrom(1024) #接收访问设备的信息和地址
        if msg ==b"q" or msg ==b"Q":    
            break
        print(msg.decode("utf-8"))
        strvar = input("请输入发送的内容:")
        sk.sendto(strvar.encode("utf-8"),addr) #发送内容
# 4.关闭连接
sk.close()
客户端
# 客户端
import socket

# 1.建立udp对象
sk = socket.socket(type = socket.SOCK_DGRAM)

# 2.收发信息的逻辑
while True:
    strvar = input("请输入您要发送的内容(按q退出):")
    sk.sendto(strvar.encode("utf-8"),("127.0.0.1",8002)) #发送数据
    if strvar.upper() =="Q":
        break
    msg,addr = sk.recvfrom(1024) #接收数据信息和地址
    print(msg.decode("utf-8"))

# 3.关闭连接
sk.close()

4.tcp黏包

原因:
[发送端]出现黏包: 1.数据太小, 2.数据之间时间间隔太短了;
[接收端]出现黏包: 接受数据太慢了
struct 模块
"""
pack   打包
	把任意长度数字转换成具有固定4个字节长度的字节流
unpack 解包
	把4个字节长度的值恢复成原来的数字,返回的是数字元组
"""
# i => int 要转换的当前类型是整型 数字范围-21亿~21亿
# pack 打包
res = struct.pack("i",191992131) #打包
print(res,len(res)) # b'C\x91q\x0b' 4
#unpack 解包成数字元组
tup = struct.unpack("i",res) #解包成数字元组
print(tup,type(tup)) #(191992131,) <class 'tuple'>
res = tup[0] #取出元组数字
print(res,type(res)) # 191992131 <class 'int'>
解决黏包办法(struct模块)

服务端 :

# 服务端
import socket,struct

sk = socket.socket() #建立对象
sk.bind(("127.0.0.1",8000)) #绑定IP端口 注册网络
sk.listen() #打开监听
conn,addr = sk.accept() #建立连接
# 发送消息
strvar = input("请输入你想要发送的数据:")
msg = strvar.encode() #转化字节流
num = len(msg) #字节流大小
res = struct.pack("i",num) #打包4个字节的字节流
conn.send(res) #先发送数据大小
conn.send(msg) #再发送真实数据

conn.send("贾英贺".encode("utf-8"))

conn.close() #关闭连接
sk.close() #退还端口

客户端 :

# 客户端
import socket,struct

sk = socket.socket() #建立对象
sk.connect(("127.0.0.1",8000)) #连接服务端
# 接收消息
msg = sk.recv(4) #第一次接收数据大小
tup = struct.unpack("i",msg) #解包成数字元组
num = tup[0] #提取数字
msg1 = sk.recv(num) #第二次接收真实数据,按第一次提取数字大小截取
print(msg1.decode("utf-8"))

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

sk.close()
posted @ 2020-12-25 20:10  十九分快乐  阅读(63)  评论(0编辑  收藏  举报