8.23_python_lx_day30

一.TCP基本语法

import socket

(1)服务端

<1>创建一个socket对象

sk = socket.socket()

<2>绑定对应的ip和端口号(让其他主机在网络中可以找得到)

#127.0.0.1代表本地ip
sk.bind( ("127.0.0.1",9001) )

<3>开启监听

sk.listen()

<4>建立三次握手

conn,addr = sk.accept()

<5>处理收发数据的逻辑

#recv 接收 send 发送
res = conn.recv(1024) # 代表一次最多接收1024个字节
print(res.decode('utf-8'))

<6>四次挥手

conn.close()

<7>退还端口

sk.close()

(2)客户端

<1>创建一个socket对象

sk = socket.socket()

<2>与服务器建立连接

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

<3>发送数据(只能发送二进制的字节流)

sk.send('需要发送的字符串'.encode('utf-8'))

<4>关闭连接

sk.close()

二.TCP循环发送消息

(1)服务端

<1>创建一个socket对象

sk = socket.socket()

<2>绑定对应的ip和端口号(让其他主机在网络中可以找得到)

#127.0.0.1代表本地ip
sk.bind( ("127.0.0.1",9001) )

<3>开启监听

sk.listen()

<5>处理收发数据的逻辑

while True:
    #<4>三次握手
    conn,addr = sk.accept()
    while True:
        res = conn.recv(1024)
        print(res.decode())
        strvar = input("请输入服务端要给客户端发送的内容")
        conn.send(strvar.encode())
        if strvar.upper() == "Q":
            break

<6>四次挥手

conn.close()

<7>退还端口

sk.close()

(2)客户端

<1>.创建socket对象

sk = socket.socket()

<2>连接服务端

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

<3>收发数据

while True:
    strvar = input("请输入您要发送的内容:")
    sk.send(strvar.encode())
    res = sk.recv(1024)
    if res == b"q" or res == b"Q":
        break
    print(res.decode())

<4>关闭连接

sk.close()

三.udp基本语法

(1)服务端

<1>创建udp对象

sk = socket.socket(type=socket.SOCK_DGRAM)

<2>绑定地址端口号

sk.bind( ("127.0.0.1",9000) )

<3>udp服务器,在一开始只能够接受数据

msg,cli_addr = sk.recvfrom(1024)
print(msg.decode())
print(cli_addr)
# 服务端给客户端发送数据
msg = "发送的字符串"
sk.sendto(msg.encode(),cli_addr)

 

<4>关闭连接

sk.close()

(2)客户端

<1>创建udp对象

sk = socket.socket(type = socket.SOCK_DGRAM)

<2>收发数据的逻辑

# 发送数据
msg = "你好,你是mm还是gg"
# sendto( 消息,(ip,端口号) )
sk.sendto( msg.encode() ,  ("127.0.0.1",9000)  )
# 接受数据
msg,server_addr = sk.recvfrom(1024)
print(msg.decode())
print(server_addr)

<3>关闭连接

sk.close()

四.udp循环发消息

(1)服务端

<1>创建udp对象

sk = socket.socket(type=socket.SOCK_DGRAM)

<2>绑定地址端口号

sk.bind( ("127.0.0.1",9000) )

<3>udp服务器,在一开始只能够接受数据

while True:
    # 接受消息
    msg,cli_addr = sk.recvfrom(1024)
    print(msg.decode())
    message = input("服务端给客户端发送的消息是?:")
    # 发送数据
    sk.sendto(message.encode() , cli_addr)

<4>关闭连接

sk.close()

五.黏包

  • 黏包出现的两种情况:
    •     (1) 发送端发送数据太快
    •   (2) 接收端接收数据太慢

(1)struct

  • pack :
  •   把任意长度数字转化成具有固定4个字节长度的字节流
  • unpack :
  •   把4个字节值恢复成原来的数字,返回最终的是元组
import struct
# pack
# i => int 要转化的当前数据是整型
# pack 的范围 -2147483648 ~ 2147483647 21个亿左右
res = struct.pack("i",2100000000)
print(res , len(res)) # len(res) => 4

# unpack
# i => 把对应的数据转换成int整型
tup = struct.unpack("i",res)
print(tup) # (2100000000,)
print(tup[0]) #2100000000
  • 解决黏包场景:
  •   应用场景在实时通讯时,需要阅读此次发的消息是什么
  • 不需要解决黏包场景:
  •   下载或者上传文件的时候,最后要把包都结合在一起,黏包无所谓

(2)使用struct解决黏包问题

<1>服务端

import socket
import struct
sk = socket.socket()
sk.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sk.bind( ("127.0.0.1",9000) )
sk.listen()
conn,addr = sk.accept()
# 处理收发数据的逻辑
strvar = input("请输入你要发送的数据")
msg = strvar.encode()
length = len(msg)
res = struct.pack("i",length)
# 第一次发送的是字节长度
conn.send(res)
# 第二次发送真实的数据
conn.send(msg)
# 第三次发送真实的数据
conn.send("世界真美好123".encode())
conn.close()
sk.close()

<2>客户端

import socketimport struct
sk = socket.socket()
sk.connect( ("127.0.0.1",9000) )
# 处理收发数据的逻辑
# 第一次接受的是字节长度
n = sk.recv(4)
tup = struct.unpack("i",n)
n = tup[0]
# 第二次接受真实的数据
res = sk.recv(n)
print(res.decode())
# 第三次接受真实的数据
res = sk.recv(1024)
print(res.decode())
sk.close()

 

posted @ 2020-08-24 00:37  Magicianlx  阅读(67)  评论(0编辑  收藏  举报