|
|
|
|||||
|
Peer to Peer problem
Hello, i am new to ICE and using Slice for my current C++ project under WindowsXP with Visual Studio 2003. The project has a peer to peer network architecture. The problem now is when the third peer joins the system just crashed ramdomly.
I also wrote up a simple test program and had the same problem. The protype code is like this: ... ... while(true) { if(time > TIME_INTERVAL) { for(int i = 0; i < sizeofDataobject; ++i) { sendInt(dataObejct[i]->getInt()); sendDouble(dataObejct[i]->getDouble()); } } } ..... Two peers can communicate very well but when the third peer joins a windows crash dialog pops. It seems to me that the nested while-for loop caused some threading problem but not so sure. Please let me know if you need more information. Thanks in advance. Charles |
|
|||||
|
Hey Matthew,
Thanks for your prompt reply, here is more details, The Slice module file we created: module osgart { module net { sequence <double> DoubleSeq; struct Matrix { DoubleSeq vals; }; class Contact { void receiveMatrix(Matrix m, int msgTypeID, int peerID); void receiveDouble(double d, int msgTypeID, int peerID); void receiveInt(int i, int msgTypeID, int peerID); void receiveString(string s, int msgTypeID, int peerID); void announce(Contact* c); }; }; }; In the application we have CommunicationManager Class that init the number of contacts as such: int argc = 0; char* argv[1] = {""}; ic = Ice::initialize(argc, argv); // Create and register contact ContactI* contact = new ContactI(); ss << "tcp -p " << port << " -h " << host << ":udp -p " << port << " -h " << host; Ice::ObjectAdapterPtr adapter = ic->createObjectAdapterWithEndpoints("OSGART.Collab ", ss.str()); adapter->add(contact, ic->stringToIdentity("contact")); adapter->activate(); // Iterate through peers, grab their contacts. for (vector<Peer>::const_iterator it = peers.begin() ; it != peers.end() ; it ++) { if (peerID != it->id) { stringstream ss; ss.flush(); ss << "contact:tcp -h " << it->host << " -p " << it->port << "\n"; std::cout << ss.str(); try { ContactPrx cp = ContactPrx::checkedCast(ic->stringToProxy(ss.str())); cp->announce(ContactPrx::uncheckedCast(adapter->createProxy(ic->stringToIdentity("contact")))); contacts.push_back(cp); } catch (...) { std::cout << "failed to connect to host " << it->host << ":" << it->port << "\n"; std::cout << "This is the server." << std::endl; } } } Then in the main program: int main(int argc, char* argv[]) { CommunicationManager::instance()->start(); osg::Timer_t s, t = osg::Timer::instance()->tick(); osg::MatrixTransform* targetTrans = new osg::MatrixTransform(); targetTrans->setMatrix(osg::Matrix::translate(osg::Vec3d(0, 0, 25))); while(true) { s = osg::Timer::instance()->tick(); if (osg::Timer::instance()->delta_m(t, s) > NET_UPDATE_INTERVAL) { t = s; for(int i = 0; i < 3; ++i){ CommunicationManager::instance()->sendMatrix(targetTrans->getMatrix(), 0); CommunicationManager::instance()->sendInt(1, PEER_VISIBILITY); } } } return 0; } One of the sending data methods look like this: void CommunicationManager::sendInt(int i, int msgTypeID) { int peerID = this->getPeerID(); for (vector<ContactPrx>::iterator it = contacts.begin() ; it != contacts.end() ; it ++) { (*it)->receiveInt(i, msgTypeID, peerID); } } This test program is similar to my project and has the same problem. |
|
||||||
|
Hi Charles,
I don't see any obvious problem in your code. As Matthew suggested, the best would be to post a small yet complete test-case that reproduces the problem. If this is not feasible, I'd recommend to create debug build of you application and to try to get a stack trace when you get this crash. This should give an idea of where the problem is. Note that Ice is fully thread-safe, and you get concurrent requests only if you start threads yourself (in a client) or you configure Ice to use several threads (on the server side). By default, Ice uses only one thread to dispatch all requests on the server side. Best regards, Bernard |
|
|||||
|
Hey Bernard,
Thanks for your reply. I have attached a zip file and please have a look the small test case. You might want to run the example for several times if it does not crash at the first time. Cheers Charles |
|
||||||
|
Just a couple of notes on your implementation. I don't think any of these issues in particular are causing the problem you mention, however, addressing these issues might help you understand Ice a little better and simplify your application design:
Code:
// Create and register contact ContactI* contact = new ContactI(); Code:
adapter->add(contact, ic->stringToIdentity("contact"));
//...
ss << "contact:tcp -h " << it->host << " -p " << it->port << "\n";
Furthermore, it looks to me like your communications manager class is more or less an event distributor. You would be better off using IceStorm to do this. |
|
||||||
|
I took a look at your code. The problem is that your client is also a server and thus has two threads of control. The first is the main thread where you are calling CommunicatorManager::sendDouble and such. The second is the dispatch threads in which the Ice runtime calls upon the servant (that is the thread that calls ContactI::receiveDouble).
Your problem comes in when ContactI::announce is called. This modifies the contact list at the same time as the main thread is calling CommunicationManager::sendDouble. This concurrent modification is not thread safe and results in the issue that you are seeing. In short, you need to mutex protect the contact list. Futhermore, you are not correctly dealing with exceptions when calling the proxy methods, so any client that drops will cause the entire application to terminate. If you used IceStorm instead then this would be a non-issue (as would concurrent modification of the contact list for that matter since that would all be managed by IceStorm itself). I also don't think that busy looping in main is so good either ![]() |
![]() |
| Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
| Thread Tools | |
| Display Modes | Rate This Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| how can i get peer ip_address in server side? | socketref | Help Center | 1 | 05-12-2006 03:06 PM |
| Peer-to-peer over VPN connections | rhochmuth | Help Center | 2 | 02-13-2004 08:13 AM |