qicosmos / rest_rpc

modern C++(C++11), simple, easy to use rpc framework
MIT License
1.66k stars 365 forks source link

乱码 #97

Open dftan-github opened 1 year ago

dftan-github commented 1 year ago

我在win11 x64上写了个测试,发现subscribe响应时传过来的首字变成乱码,后面的正常,?? 而编译运行你们自带的example没有这个问题,unicode、非unicode、MSGPACK_NO_BOOST、console、mfc这些组合我都试了,都一样的问题

期待能得到回复,先谢了

注: vs2022 使用的是c++14 rest_rpc是3-28-23从github下载回来的 我是在同一个exe中开启的server及client

image

qicosmos commented 1 year ago

我这周看一下这个问题,可能是最近的某个pr引入的问题。

qicosmos commented 1 year ago

你的server 代码是什么样的?我测试example里面的test_sub1 看到订阅的数据是正常的。

// client
void test_sub1() {
  rpc_client client;
  client.enable_auto_reconnect();
  client.enable_auto_heartbeat();
  bool r = client.connect("127.0.0.1", 9000);
  if (!r) {
    return;
  }

  client.subscribe("key", [](string_view data) { 
    std::cout << data << "\n";
  });

std::string str;
std::cin>>str;
}
dftan-github commented 1 year ago

你的server 代码是什么样的?我测试example里面的test_sub1 看到订阅的数据是正常的。

// client
void test_sub1() {
  rpc_client client;
  client.enable_auto_reconnect();
  client.enable_auto_heartbeat();
  bool r = client.connect("127.0.0.1", 9000);
  if (!r) {
    return;
  }

  client.subscribe("key", [](string_view data) { 
    std::cout << data << "\n";
  });

std::string str;
std::cin>>str;
}

这里发不了压缩包吗?想要把测试程序源码发过去给你看看

dftan-github commented 1 year ago

全部相关代码如下 .h

class CMFCApplication2Dlg : public CDialogEx { rest_rpc::rpc_client mAIOClient; rpc_server aioSvr;// (9000, std::thread::hardware_concurrency()); std::thread thdAIOSvr; HWND hwndSvr; // 构造 public: CMFCApplication2Dlg(CWnd pParent = nullptr); // 标准构造函数 ~CMFCApplication2Dlg() { if (thdAIOSvr) delete thdAIOSvr; }

.cpp

CMFCApplication2Dlg::CMFCApplication2Dlg(CWnd pParent /=nullptr*/) : CDialogEx(IDD_MFCAPPLICATION2_DIALOG, pParent) , aioSvr(9000, std::thread::hardware_concurrency())

{ thdAIOSvr = nullptr; hwndSvr = NULL; m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); }

BOOL CMFCApplication2Dlg::OnInitDialog() { CDialogEx::OnInitDialog();

// 将“关于...”菜单项添加到系统菜单中。

// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
    BOOL bNameValid;
    CString strAboutMenu;
    bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
    ASSERT(bNameValid);
    if (!strAboutMenu.IsEmpty())
    {
        pSysMenu->AppendMenu(MF_SEPARATOR);
        pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    }
}
thdAIOSvr=new std::thread([&] {

    aioSvr.register_handler("publish_by_token", [&](rpc_conn conn,
        std::string key,
        std::string token,
        std::string val) {
            aioSvr.publish_by_token(std::move(key), std::move(token), std::move(val));
        });

    aioSvr.register_handler("publish",
        [&](rpc_conn conn, std::string key,
            std::string token, std::string val) {
                aioSvr.publish(std::move(key), std::move(val));
        });
    aioSvr.set_network_err_callback(
        [](std::shared_ptr<connection> conn, std::string reason) {
            std::cout << "remote client address: " << conn->remote_address()
                << " networking error, reason: " << reason << "\n";
        });

    aioSvr.run();

    });

// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
//  执行此操作
SetIcon(m_hIcon, TRUE);         // 设置大图标
SetIcon(m_hIcon, FALSE);        // 设置小图标

// TODO: 在此添加额外的初始化代码
thdAIOSvr->detach();
mAIOClient.enable_auto_reconnect();
mAIOClient.enable_auto_heartbeat();

bool r = mAIOClient.connect("127.0.0.1", 9000);
mAIOClient.subscribe("test", [](string_view data) {
    std::cout << data << std::endl;
    int i;
    i = 0;
    });

return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE

}

void CMFCApplication2Dlg::OnBnClickedOk() { // TODO: 在此添加控件通知处理程序代码

if (mAIOClient.has_connected())
{
    mAIOClient.publish("test", "hello subscriber");
}
//CDialogEx::OnOK();

}

qicosmos commented 1 year ago

subscribe 得到的数据需要解包一下:

client.subscribe("key", [](string_view data) { 
    std::cout << data << "\n";
  });

改成

client.subscribe("key", [](string_view data) {
      msgpack_codec codec;
      auto str = codec.unpack<std::string>(data.data(), data.size());
      std::cout << str << "\n";
  });

这样就没有乱码了,略有不便,后面我改一下,改成让框架自动去解包。

dftan-github commented 1 year ago

訂閱得到的數據需要解包下一篇:

client.subscribe("key", [](string_view data) { 
    std::cout << data << "\n";
  });

改成

client.subscribe("key", [](string_view data) {
      msgpack_codec codec;
      auto str = codec.unpack<std::string>(data.data(), data.size());
      std::cout << str << "\n";
  });

這樣就沒有亂碼了,略有不便,後面我改一下,改成讓框架自動去解包。

按你的指引,成功解决了问题,谢啦