31 socket套接字 struct模块

socket(套接字)
  基于socket实现客户端与服务端通信 

服务端套接字函数

s.bind()    绑定(主机,端口号)到套接字

s.listen()  开始TCP监听

s.accept()  被动接受TCP客户的连接,(阻塞式)等待连接的到来

 

客户端套接字函数

s.connect()    主动初始化TCP服务器连接

s.connect_ex()  connect()函数的扩展版本,出错时返回出错码,而不是抛出异常

 

公共用途的套接字函数

s.recv()       接收TCP数据

s.send()       发送TCP数据(send在待发送数据量大于己端缓存区剩余空间时,数据丢失,不会发完)

 socket初识

  127.0.0.1:本地回环地址,只能本机访问

-----------------------------服务端------------------------------
import socket

server = socket.socket()  # 类似于买手机
server.bind(('127.0.0.1', 8080))  # 类似于插手机卡   bind((IP,PORT))
server.listen(5)  # 开机   半连接池

conn, addr = server.accept()  # 待机等待接电话

data = conn.recv(1024)  # 接听别人说话 只接收1024个字节 bytes
print(data)
conn.send(b'hello!')  # 跟别人说话

conn.close()  # 关闭通信连接
server.close()  # 关闭服务端


-----------------------------客户端------------------------------
import socket

client = socket.socket()
client.connect(('127.0.0.1', 8080))  # 找服务器

client.send(b'hello how much?')
data = client.recv(1024)
print(data)

client.close()

 TCP协议的特点

  会将数据量比较小的,并且时间间隔比较短的数据,一次性打包发送给接收端

-----------------------------服务端------------------------------
import socket

server = socket.socket()
server.bind(('127.0.0.1',8088))
server.listen(5)  # 半连接池


conn,addr = server.accept()
data = conn.recv(1024)
print(data)
data = conn.recv(1024)
print(data)
data = conn.recv(1024)
print(data)

>>>:b'hellohellohello'
   b''
   b''


-----------------------------客户端------------------------------
import socket

client = socket.socket()
client.connect(('127.0.0.1',8088))


client.send(b'hello')
client.send(b'hello')
client.send(b'hello')            

通信循环

-----------------------------服务端------------------------------
import socket

"""
服务端:
要有固定的ip和port
24小时不间断提供服务
"""
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)

conn, addr = server.accept()  # 阻塞

while True:
    try:
        data = conn.recv(1024)  # 阻塞
        if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况
        print(data)
        conn.send(data.upper())
    except ConnectionResetError:
        break

conn.close()
server.close()


-----------------------------客户端------------------------------
import socket

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

while True:
    msg = input('>>>:').encode('utf-8')
    if len(msg) == 0: continue
    client.send(msg)
    data = client.recv(1024)
    print(data)

struct模块

import struct

data = 'seionksngjgm,xmdnabnk ko'
res = struct.pack('i',len(data))

print('res:',res)   # res: b'\x18\x00\x00\x00'
print('len(res):',len(res))  # 4


ret = struct.unpack('i',res)
print('ret:',ret)  # (24,)
print('ret[0]:',ret[0])  # 24

链接循环

-----------------------------服务端------------------------------
import socket
import subprocess
import struct
import json

"""
服务端:
要有固定的ip和port
24小时不间断提供服务
"""
server = socket.socket()
server.bind(('127.0.0.1', 8081))
server.listen(5)  # 半连接池

while True:
    conn, addr = server.accept()  # 阻塞
    while True:
        try:
            data = conn.recv(1024).decode('utf-8')  # 阻塞
            if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况
            obj = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            stdout = obj.stdout.read()
            stderr = obj.stderr.read()
            print(len(stdout + stderr))

            header_dic = {
                'filename': 'cls.av',
                'len': len(stdout + stderr)
            }
            header_bytes = json.dumps(header_dic).encode('utf-8')
            # 制作报头
            header = struct.pack('i', len(header_bytes))  # 将需要发送给客户端的数据打包成固定4个字节
            conn.send(header)

            conn.send(header_bytes)

            conn.send(stdout + stderr)

        except ConnectionResetError:
            break
    conn.close()

server.close()



-----------------------------客户端------------------------------
import socket
import struct
import json

client = socket.socket()
client.connect(('127.0.0.1', 8081))

while True:
    msg = input('>>>:').encode('utf-8')
    if len(msg) == 0: continue
    client.send(msg)
    header = client.recv(4)
    # 对这个头进行解包,获取真实数据的长度

    head_len = struct.unpack('i', header)[0]
    head_dic = json.loads(client.recv(head_len).decode('utf-8'))
    print(head_dic)
    # 对需要接受的数据 进行循环接收
    total_size = head_dic['len']
    recv_size = 0
    res = b''
    while recv_size < total_size:
        data = client.recv(1024)
        res += data
        recv_size += len(data)
    print(res.decode('gbk'))

粘包问题

-----------------------------服务端------------------------------
import socket

"""
服务端:
要有固定的ip和port
24小时不间断提供服务
"""
server = socket.socket()
server.bind(('127.0.0.1', 8080))
server.listen(5)  # 半连接池

while True:
    conn, addr = server.accept()  # 阻塞
    while True:
        try:
            data = conn.recv(1024)  # 阻塞
            if len(data) == 0: break  # 针对linux和mac系统 客户端异常断开反复收空的情况
            print(data)
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()

server.close()



-----------------------------客户端------------------------------
import socket

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

while True:
    msg = input('>>>:').encode('utf-8')
    if len(msg) == 0: continue
    client.send(msg)
    data = client.recv(1024)
    print(data)

最终方法:解决粘包问题
 1.先发报头
 2.再发字典
 3.再发你的真实数据
 
 
 1.先收4个长度的报头
 2.解包拿到字典数据长度
 3.接收字典(反序列化) 》》》  获取字典里面所有信息
 4.接收真实数据

猜你喜欢

转载自www.cnblogs.com/zhouyongv5/p/10797998.html