C ++ Boost序列化:输入流错误

时间:2017-11-08 15:17:28

标签: c++ serialization boost zeromq

高级C ++开发人员,

我尝试使用@Override public boolean onQueryTextChange(String newText) { newText = newText.toLowerCase(); Query search = mDatabaseReference.orderByChild("country").startAt(newText).endAt(newText+"\uf8ff"); FirebaseRecyclerAdapter<CardItem, SearchViewHolder> firebaseRecyclerAdapter22 = new FirebaseRecyclerAdapter<CardItem, SearchViewHolder>( CardItem.class, R.layout.single_card, SearchViewHolder.class, search ) { @Override protected void populateViewHolder(final SearchViewHolder hiViewHolder, final CardItem model, int position) { hiViewHolder.setPicture(model.getThumbPhoto() , getApplicationContext()); hiViewHolder.setTitle(model.getTitle()); hiViewHolder.setCountry(model.getCountry()); hiViewHolder.setPrice("Price: $" + model.getPricePerGuest()); } }; mTripList.setAdapter(firebaseRecyclerAdapter22); return false; } }); return super.onCreateOptionsMenu(menu); } zmq通过网络发送C ++课程。

概念是序列化客户端上的类boost::serialization。然后使用PlayCommand将其发送到服务器。并在服务器上反序列化。

这在应用程序的其余部分中工作正常。出于某种原因,我在不时反序列化服务器上​​的zmq时会收到输入流错误。我无法弄清楚为什么它有时会抛出这个例外而有时不会。

这似乎是一个时间敏感的问题。我是否必须在某个时候等待让助推做到这一点?

PlayCommand
std::shared_ptr<PlayCommand> _exe(dynamic_cast<PlayCommand*>(_cmd.get()));


    zmq::context_t _ctx(1);
    zmq::socket_t _skt(_ctx, ZMQ_PUB);
    _skt.connect("tcp://0.0.0.0:" + this->kinect_daemon_com_port);

    std::stringstream _type_stream;
    std::stringstream _exe_stream;
    boost::archive::text_oarchive _type_archive(_type_stream);
    boost::archive::text_oarchive _exe_archive(_exe_stream);
    _type_archive << _type;
    _exe_archive << *_exe.get();


    std::string _type_msg_str = _type_stream.str();
    std::string _exe_msg_str = _exe_stream.str();
    zmq::message_t _type_msg(_type_msg_str.length());
    zmq::message_t _exe_msg(_exe_msg_str.length());


    memcpy(_type_msg.data(), _type_msg_str.data(), _type_msg_str.length());
    memcpy(_exe_msg.data(), _exe_msg_str.data(), _exe_msg_str.length());

    _skt.send(_type_msg, ZMQ_SNDMORE);
    _skt.send(_exe_msg, 0);

完整的项目位于github:rgbd-calibrgbd-calib-py。 重要的文件是rgbd-calib中的/framework/ZMQMessageResolver.cpp和rgbd-calib-py中的/src/KinectDaemon.cpp。

我将不胜感激。

第一个见解 我检查了共享的 void ZMQMessageResolver::resolve_message(std::shared_ptr<Event> _event, unsigned _unique_thread_id) { std::cout << "ZMQMessageResolver::resolve_message(std::shared_ptr<Event> _event, unsigned _unique_thread_id)" << std::endl; std::shared_ptr<ZMQMessageEvent> _zmq_event = std::static_pointer_cast<ZMQMessageEvent>(_event); //(static_cast<ZMQMessageEvent*>(_event.get())); ZMQMessageType _type; PlayCommand _cmd; auto _messages = _zmq_event->get_data(); auto _type_string = std::string(static_cast<char*>(_messages->front()->data()), _messages->front()->size()); auto _cmd_string = std::string(static_cast<char*>(_messages->back()->data()), _messages->back()->size()); std::stringstream _type_stream{_type_string}; std::istringstream _cmd_stream{_cmd_string}; boost::archive::text_iarchive _type_archive{_type_stream}; boost::archive::text_iarchive _cmd_archive{_cmd_stream}; std::cout << "1" << std::endl; _type_archive >> _type; std::cout << "2" << std::endl; _cmd_archive & _cmd; std::cout << "3" << std::endl; std::shared_ptr<ThreadEvent> _thread_event = std::make_shared<ThreadEvent>(_zmq_event->get_event_message()); _cmd.execute(_thread_event); std::lock_guard<std::mutex> _lock{*this->thread_mutex}; this->finished_threads.push_back(_unique_thread_id); } 实例。我找不到任何这样的线程安全应该是一个非问题。

我发现其他开发人员也遇到了ZMQ多部分消息的问题。在我的情况下,也许这可能是一个问题。也许有人作为经验。发送和接收多部分消息时是否必须采取任何安全措施?

2 个答案:

答案 0 :(得分:0)

如果它的时间敏感,毫无疑问它与提升无关:显示的提升代码是完全同步和本地的。如果您不总是收到完整的流,则会收到此错误。同样,如果解释接收到的数据存在协议错误,您可能会收到损坏的数据。

这两种情况都很容易导致&#34;输入流错误&#34;。

我没有使用0MQ的经验,所以我不知道所显示的代码是否会收到不完整的消息,但我会调查一下。

一个小小的注意事项是,有一个public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final String BASE_URL = "https://raw.githubusercontent.com/David-Haim/CountriesToCitiesJSON/master/countriesToCities"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); CountriesAPI countriesAPI = retrofit.create(CountriesAPI.class); Call<Country> call = countriesAPI.getCountries(); call.enqueue(new Callback<Country>() { @Override public void onResponse(Call<Country> call, Response<Country> response) { Log.d(TAG, "onResponse: Server Response: " + response.toString()); Log.d(TAG, "onResponse: received information: " + response.body().toString()); ArrayList<String> citiesList = response.body().getCities(); for(int i = 0; i<citiesList.size(); i++){ Log.d(TAG, "onResponse: \n" + "country: " + citiesList.get(i) ); } } @Override public void onFailure(Call<Country> call, Throwable t) { Log.e(TAG, "onFailure: Something went wrong" + t.getMessage()); Toast.makeText(MainActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show(); } }); } } public interface CountriesAPI { String BASE_URL = "https://raw.githubusercontent.com/David-Haim/CountriesToCitiesJSON/master/countriesToCities"; @GET(".json") Call<Country> getCountries(); } public class Country { @SerializedName("country") @Expose private ArrayList<String> countrys; @SerializedName("country") @Expose private ArrayList<String> cities; public ArrayList<String> getCountrys() { return countrys; } public void setCountrys(ArrayList<String> countrys) { this.countrys = countrys; } public ArrayList<String> getCities() { return cities; } public void setCities(ArrayList<String> cities) { this.cities = cities; } @Override public String toString() { return "Country{" + "countrys=" + countrys + ", cities=" + cities + '}'; } } 和另一个stringstream相当奇怪。寻求行为可能存在差异。

答案 1 :(得分:0)

让我在故事的ZeroMQ部分加几美分:

事实#1:
ZeroMQ从不提供一块垃圾,它提供完整的消息(因为它已被发送)或者什么都没有

此主要设计功能有助于理清所声称的潜在问题之一。

如果应用程序确实收到了传递的ZeroMQ消息,则可以确定它是从远程进程调度的形状和声音副本。它完全一样。 Pullstop。

事实#2:从ZeroMQ API v2.xx 一开始就警告永不分享

,ZeroMQ架构师和福音传道者在每一章都做

从上面描述的代码看来不清楚。

如果在上面的上下文中实例化一个ZeroMQ套接字AccessPoint( SUB - 类型),拥有此类AccessPoint资源的线程是唯一可以使用此类资源进行操作的线程从来没有“让”任何其他触摸这个玩具。决不。虽然可能会有一些最近的谈判和努力重新设计ZeroMQ核心,以便添加一个线程安全的事后,我仍然对这些动作持怀疑态度,主要是确保无阻塞的高性能+低分布式计算中的自适应动机设计永远不应该共享一个共同的部分,因为开销的成本和主要安全性的损失(这不容易被任何线程间信令/锁定/阻塞事后买回)

您可以查看代码,以便确认或拒绝任何类型的共享ZeroMQ实例(Context是另一个单独的主题),对于检测到共享片段的情况,您的团队应该重新审核 - 设计代码以避免它。

是。避免共享,ZeroMQ工具将为您提供服务。