项目之socket

客户端socket

客户端套接字完成的任务很统一,发送请求,接收请求结果
可以封装成一个方法
使用的tcp协议存在粘包问题,故需要自定义报头

import json
import struct

#项目需要使用到时间,json无法序列化时间对象
#以下操作使json将时间对象序列化
class Myjson(json.JSONEncoder):
    def default(self, field):
        if isinstance(field, datetime):
            return field.strftime("%Y-%m-%d %X")
        return json.JSONEncoder.default(self, field)


def send_data(c, dic):
    json_data = json.dumps(dic, cls=Myjson).encode("utf-8")
    len_data = struct.pack("i", len(json_data))
    c.send(len_data)
    c.send(json_data)


def recv_data(c):
    struct_len = c.recv(4)
    data_len = struct.unpack("i", struct_len)[0]
    json_data = c.recv(data_len).decode("utf-8")
    dic = json.loads(json_data)
    return dic

from socket import socket
from conf.settings import CLIENT_CONF
from lib.common import recv_data,send_data
c = socket()
c.connect((CLIENT_CONF["host"],CLIENT_CONF["port"]))

#client 工作
def client_run(req_dic):
    send_data(c,req_dic)
    res_dic = recv_data(c)
    return res_dic

服务端socket
与客户端的区别,需要支持并发
使用多路复用达到并发目的
使用select模块帮我们检测可操作连接
recv操作是耗时的,从客户端操作系统缓存到服务端操作系统缓存,
而send操作默认从应用程序将消息发到缓存就算完成,故是很快的
故项目此处只检测可读连接,大型项目需检测可写连接,因为内存可能会满

import select
from core import user,admin
from socket import socket
from conf.settings import SERVER_CONF
from lib import common
s = socket()
s.bind((SERVER_CONF["host"],SERVER_CONF["port"]))
s.listen(5)
#完成任务的分发
def admin_interface(req_dic,c=0):
    return admin.main(req_dic,c)

def user_interface(req_dic,c=0):
    return user.main(req_dic,c)

func_dic={
    1:admin_interface,
    0:user_interface
}

asy_work = ["asy_upload_movie","asy_download_movie"]

def client_work(r):
    req_dic = common.recv_data(r)
    if not req_dic:return
    if req_dic["user_type"] in func_dic:
        if req_dic["opt"] in asy_work:
            res_dic = func_dic[req_dic["user_type"]](req_dic,r)
        else:
            res_dic = func_dic[req_dic["user_type"]](req_dic)
    else:
        res_dic = {"status":"ng","msg":"user_type does not exist"}
    if res_dic:
        common.send_data(r,res_dic)
#select模块
rlist = [s,]
def server_run():
    while True:
        rl,_,_, = select.select(rlist,[],[])
        for r in rl:
            if r == s:
                c,_ = s.accept()
                rlist.append(c)
            else:
                try:
                    client_work(r)
                except ConnectionResetError:
                    r.close()
                    rlist.remove(r)
posted @ 2019-02-24 16:42  robertzhou  阅读(416)  评论(0编辑  收藏  举报