31 socket套接字 struct模块

Posted zhouyongv5

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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(bhello!)  # 跟别人说话

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


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

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

client.send(bhello 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)

>>>:bhellohellohello
   b‘‘
   b‘‘


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

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


client.send(bhello)
client.send(bhello)
client.send(bhello)            

通信循环

-----------------------------服务端------------------------------
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.接收真实数据

以上是关于31 socket套接字 struct模块的主要内容,如果未能解决你的问题,请参考以下文章

网络编程之套接字socket

socket 错误之:OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。

网络编程(part11)--socket模块方法及socket套接字属性

socket模块(套接字模块)

Python 31 TCP协议 socket套接字

socket网络编程:最终版本的ssh模拟程序(标准cs构架模板)