国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

在tornado中使用tcpserver和tcpclient實現(xiàn)echo服務(wù)器

liukai90 / 2138人閱讀

摘要:本文主要介紹了在框架中使用實現(xiàn)簡單服務(wù)器的過程。在網(wǎng)絡(luò)通信中,需要發(fā)送二進制流數(shù)據(jù)函數(shù)負責(zé)數(shù)據(jù)組包,即將數(shù)據(jù)按照規(guī)定的傳輸協(xié)議組合起來函數(shù)負責(zé)數(shù)據(jù)拆包,即按照規(guī)定的協(xié)議將數(shù)據(jù)拆分開來。不多說,具體實現(xiàn)代碼咱們來看一下。

本文主要介紹了在tornado框架中,使用tcpserver,tcpclient,struct.pack(),struct.unpack實現(xiàn)簡單echo服務(wù)器的過程。

在網(wǎng)絡(luò)通信中,需要發(fā)送二進制流數(shù)據(jù);struct.pack()函數(shù)負責(zé)數(shù)據(jù)組包,即將數(shù)據(jù)按照規(guī)定的傳輸協(xié)議組合起來;struct.unpack()函數(shù)負責(zé)數(shù)據(jù)拆包,即按照規(guī)定的協(xié)議將數(shù)據(jù)拆分開來。

不多說,具體實現(xiàn)代碼咱們來看一下。

tcp客戶端代碼如下:

# coding=utf-8


import struct
import logging

from tornado import ioloop, gen
from tornado.tcpclient import TCPClient


"""
tcpclient-struct.pack()組包
發(fā)送數(shù)據(jù)包格式:消息頭+消息體
消息頭:消息發(fā)送者(4字節(jié))+消息接收者(4字節(jié))+消息類型(1字節(jié))+消息體中數(shù)據(jù)長度(4字節(jié))
消息體:待發(fā)送數(shù)據(jù)
struct.unpack()拆包
接收數(shù)據(jù)包格式:消息頭+消息體
消息頭:消息發(fā)送者(4字節(jié))+消息類型(1字節(jié))+消息體中數(shù)據(jù)長度(4字節(jié))
消息體:待接收數(shù)據(jù)
"""


logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)


class ChatClient(object):
    def __init__(self, host, port):
        self.host = host
        self.port = port

    @gen.coroutine
    def start(self):
        self.stream = yield TCPClient().connect(self.host, self.port)
        while True:
            yield self.send_message()
            yield self.receive_message()

    @gen.coroutine
    def send_message(self):
        # 待發(fā)送數(shù)據(jù)
        msg = input("輸入:")
        bytes_msg = bytes(msg.encode("utf-8"))
        # 消息發(fā)送者
        chat_id = 10000000
        # 消息接收者
        receive_id = 10000001
        # 消息類型 1-文本 2-圖片 3-語音 4-視頻 等
        msg_type = 1

        binary_msg = struct.pack("!IIBI"+str(len(msg))+"s", chat_id, receive_id, msg_type, len(msg), bytes_msg)
        # 發(fā)送數(shù)據(jù)
        yield self.stream.write(binary_msg)

    @gen.coroutine
    def receive_message(self):
        """
        接收數(shù)據(jù)
        :return:
        """
        try:
            logger.debug("receive data ...")
            # 消息發(fā)送者 4字節(jié)
            sender = yield self.stream.read_bytes(4, partial=True)
            sender = struct.unpack("!I", sender)[0]
            logger.debug("sender:%s", sender)

            # 消息類型 1字節(jié)
            msg_type = yield self.stream.read_bytes(1, partial=True)
            msg_type = struct.unpack("!B", msg_type)[0]
            logger.debug("msg_type:%s", msg_type)

            # 消息長度 4字節(jié)
            msg_len = yield self.stream.read_bytes(4, partial=True)
            msg_len = struct.unpack("!I", msg_len)[0]
            logger.debug("msg_len:%s", msg_len)

            # 真實數(shù)據(jù)
            data = yield self.stream.read_bytes(msg_len, partial=True)
            data = struct.unpack("!" + str(msg_len) + "s", data)
            logger.debug("data:%s", data)
        except Exception as e:
            logger.error("tcp client exception:%s", e)


def main():
    c1 = ChatClient("127.0.0.1", 8888)
    c1.start()
    ioloop.IOLoop.instance().start()


if __name__ == "__main__":
    main()
    
    
    

tcp服務(wù)端代碼:

# coding=utf-8


import struct
import logging

from tornado.tcpserver import TCPServer
from tornado.netutil import bind_sockets
from tornado.iostream import StreamClosedError
from tornado import gen
from tornado.ioloop import IOLoop


"""
tcpserver-struct.unpack()拆包
接收數(shù)據(jù)包格式:消息頭+消息體
消息頭:消息發(fā)送者(4字節(jié))+消息接收者(4字節(jié))+消息類型(1字節(jié))+消息體中數(shù)據(jù)長度(4字節(jié))
消息體:待接收數(shù)據(jù)
struct.pack()組包
轉(zhuǎn)發(fā)數(shù)據(jù)包格式:消息頭+消息體
消息頭:消息發(fā)送者(4字節(jié))+消息類型(1字節(jié))+消息體中數(shù)據(jù)長度(4字節(jié))
消息體:待發(fā)送數(shù)據(jù)
"""


logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)


class ChatServer(TCPServer):

    PORT = 8888
    clients = dict()

    @gen.coroutine
    def handle_stream(self, stream, address):
        """
        數(shù)據(jù)拆包并解析
        :param stream:
        :param address:
        :return:
        """
        logger.debug("%s已上線", address)
        ChatServer.clients[address] = stream
        while True:
            try:
                # !表示使用大端方式解析數(shù)據(jù)
                # 消息發(fā)送者 4字節(jié)
                sender = yield stream.read_bytes(4, partial=True)
                sender = struct.unpack("!I", sender)[0]
                logger.debug("sender:%s", sender)

                # 消息接收者 4字節(jié)
                receiver = yield stream.read_bytes(4, partial=True)
                receiver = struct.unpack("!I", receiver)[0]
                logger.debug("receiver:%s", receiver)

                # 消息類型 1字節(jié)
                msg_type = yield stream.read_bytes(1, partial=True)
                msg_type = struct.unpack("!B", msg_type)[0]
                logger.debug("msg_type:%s", msg_type)

                # 消息長度 4字節(jié)
                msg_len = yield stream.read_bytes(4, partial=True)
                msg_len = struct.unpack("!I", msg_len)[0]
                logger.debug("msg_len:%s", msg_len)

                if msg_type == 1:
                    # 文本信息處理
                    logger.debug("text message ...")
                    self.handle_text_stream(stream, sender, msg_len)
                elif msg_type == 2:
                    logger.debug("picture message ...")
                    self.handle_pic_stream(stream, sender, msg_len)

            except StreamClosedError:
                logger.debug("%s已下線", address)
                del ChatServer.clients[address]
                break

    @gen.coroutine
    def handle_text_stream(self, stream, sender, msg_len):
        """
        處理文本數(shù)據(jù)
        :param stream:
        :param send_to:
        :param msg_len:
        :return:
        """
        data = yield stream.read_bytes(msg_len, partial=True)
        data = struct.unpack("!"+str(msg_len)+"s", data)
        logger.debug("data:%s", data)
        try:
            # 打包數(shù)據(jù),數(shù)據(jù)格式:數(shù)據(jù)發(fā)送者+數(shù)據(jù)類型+數(shù)據(jù)長度+數(shù)據(jù)體
            binary_msg = struct.pack("!IBI" + str(msg_len) + "s", sender, 1, msg_len, data[0])
            # 發(fā)送數(shù)據(jù)
            yield stream.write(binary_msg)
            logger.debug("="*25)
        except KeyError:
            # 將離線消息保存到數(shù)據(jù)庫
            pass

    @gen.coroutine
    def handle_pic_stream(self, stream, sender, msg_len):
        pass


if __name__ == "__main__":
    sockets = bind_sockets(ChatServer.PORT)
    server = ChatServer()
    server.add_sockets(sockets)
    IOLoop.current().start()
    

以上就是具體的代碼實現(xiàn),如有錯誤,歡迎大家與我交流指正,謝謝!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/44741.html

相關(guān)文章

  • django開發(fā)-djangotornado的不同

    摘要:中常用的幾個框架有等,今天來總結(jié)一下和的不同。本文使用的環(huán)境是。文件可以加載路由信息和項目配置信息,文件負責(zé)啟動項目。以上就簡單的比較了和幾個方面的不同,它們各有優(yōu)缺點,實際工作中可以根據(jù)不同的需求選擇不同的框架進行開發(fā)。 python中常用的幾個web框架有django, tornado, flask等,今天來總結(jié)一下django和tornado的不同。工作中django和torna...

    Reducto 評論0 收藏0
  • #網(wǎng)絡(luò)編程

    摘要:網(wǎng)絡(luò)編程網(wǎng)絡(luò)編程有常見的鏈接面向連接的,就像打電話必須要一來一往的做出回應(yīng)是不面向鏈接的,不需要做出回應(yīng)這是一個簡單的代碼例子輸入你的信息編程這是客戶端發(fā)送的信息 網(wǎng)絡(luò)編程 2017-07-12 18:51:50 bloggithub網(wǎng)絡(luò)編程有常見的tcp,udp 鏈接 tcp 面向連接的,就像打電話必須要一來一往的做出回應(yīng) udp 是不面向鏈接的, 不需要做出回應(yīng) 這是一個簡單的tc...

    winterdawn 評論0 收藏0
  • tornado 源碼分析 之 異步io的實現(xiàn)方式

    摘要:前言本文將嘗試詳細的帶大家一步步走完一個異步操作從而了解是如何實現(xiàn)異步的其實本文是對上一篇文的實踐和復(fù)習(xí)主旨在于關(guān)注異步的實現(xiàn)所以會忽略掉代碼中的一些異常處理文字較多湊合下吧接下來只會貼出部分源碼幫助理解希望有耐心的同學(xué)打開源碼一起跟蹤一遍 前言 本文將嘗試詳細的帶大家一步步走完一個異步操作,從而了解tornado是如何實現(xiàn)異步io的. 其實本文是對[上一篇文][1]的實踐和復(fù)習(xí) 主...

    xiangzhihong 評論0 收藏0
  • 1、網(wǎng)絡(luò)三要素及傳輸協(xié)議 2、實現(xiàn)UDP協(xié)議的發(fā)送端接收端 3、實現(xiàn)TCP協(xié)議的客戶端務(wù)器 4

    摘要:應(yīng)用層主要負責(zé)應(yīng)用程序的協(xié)議,例如協(xié)議協(xié)議等。在計算機中,不同的應(yīng)用程序是通過端口號區(qū)分的。區(qū)別在于,中只有發(fā)送端和接收端,不區(qū)分客戶端與服務(wù)器端,計算機之間可以任意地發(fā)送數(shù)據(jù)。 01網(wǎng)絡(luò)模型 *A:網(wǎng)絡(luò)模型 TCP/IP協(xié)議中的四層分別是應(yīng)用層、傳輸層、網(wǎng)絡(luò)層和鏈路層,每層分別負責(zé)不同的通信功能,接下來針對這四層進行詳細地講解。 鏈路層:鏈路層是用于定義物理傳輸通道,通常是對...

    CastlePeaK 評論0 收藏0
  • Tornado 4.3文檔翻譯: HTTP 服務(wù)客戶端-非阻塞 HTTP server

    摘要:譯者說于年月日發(fā)布,該版本正式支持的關(guān)鍵字,并且用舊版本編譯同樣可以使用這兩個關(guān)鍵字,這無疑是一種進步。原諒我沒排好版非阻塞非阻塞,單線程。其舊名稱仍作為一個別名。非阻塞,單線程。要使可以服務(wù)于加密的流量,需要把參數(shù)設(shè)置為一個對象。 譯者說 Tornado 4.3于2015年11月6日發(fā)布,該版本正式支持Python3.5的async/await關(guān)鍵字,并且用舊版本CPython編譯T...

    tianyu 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<