Laurens Posted October 31, 2010 Share Posted October 31, 2010 Hi everyone, Lately I have been reading up on networking and it occurred to me that in order for me to receive events I need to call WaitNetwork and specify a timeout. I suppose this means that it will halt all further execution (updating, rendering) until it either times out or receives an event. It could be easily solved with multithreading but I have heard rumours that this does not work well with the engine or should I be fine since I would only be doing networking in the other thread? Thanks! Quote Link to comment Share on other sites More sharing options...
Laurens Posted November 1, 2010 Author Share Posted November 1, 2010 So I just confirmed that WaitNetwork is indeed blocking all further executing. Specifying a timeout of 1ms in a loop is still unacceptable due to timer inaccuracy so the only way out I see now is multithreading. Should I run into any trouble if the only thing I do in the other thread is networking? Any actions taken upon network activity (for example, a "ENTITY_CREATED" event is sent across the network) would still be handled in the main thread. Thanks! Quote Link to comment Share on other sites More sharing options...
Mumbles Posted November 1, 2010 Share Posted November 1, 2010 My way around that was to implement a third party winsock library. I'm using it in a multi-threaded fashion, but when you call it to check for messages on a socket, if there's no data waiting, it returns immediately with a value of 0, and if there is data waiting, it returns a value 1, in which case then instruct the library to get the packet that's waiting. Whilst that would work fine single-threaded, if you have lots of sockets then then you have to wait longer whilst you check them all for newly arrived packets. I don't know, but being entity related, I can guess that you may get setMemBit errors occuring if you use a second thread dedicated for networking. If the first thread is trying to access an entity at the exact same time. Quote LE Version: 2.50 (Eventually) Link to comment Share on other sites More sharing options...
Canardia Posted November 1, 2010 Share Posted November 1, 2010 I'm using SDL_net, because I need SDL for many other things which LE doesn't support also, like Joysticks, Forcefeedback, Console Controllers, etc... With SDL_net I have reliable and fast cross-platform UDP networking. Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Chris Paulson Posted November 1, 2010 Share Posted November 1, 2010 I'm using SDL_net, because I need SDL for many other things which LE doesn't support also, like Joysticks, Forcefeedback, Console Controllers, etc... With SDL_net I have reliable and fast cross-platform UDP networking. Have you managed to get SDL and leadwerks to render to the same window? If so I'd like to see example code (sorry to hijack the thread). Threading with mutexs around LW commands would be best way to handle networking using LW commands. The boost stuff is good for threads, I've got example code if you need it, although not with network stuff. Quote Link to comment Share on other sites More sharing options...
Rick Posted November 1, 2010 Share Posted November 1, 2010 Of course if you want to use a different library I would always pimp RakNet. It's multi-threaded and you don't have to even worry about any of that as it's done for you. It's also cross-platform and reliable UDP. Quote Link to comment Share on other sites More sharing options...
Canardia Posted November 1, 2010 Share Posted November 1, 2010 Have you managed to get SDL and leadwerks to render to the same window? If so I'd like to see example code (sorry to hijack the thread).I open a SDL window, and then somehow hook the LE window to use it. It's part of bigger game projects, but I could make a simple demo sometime. Quote ■ Ryzen 9 ■ RX 6800M ■ 16GB ■ XF8 ■ Windows 11 ■ ■ Ultra ■ LE 2.5 ■ 3DWS 5.6 ■ Reaper ■ C/C++ ■ C# ■ Fortran 2008 ■ Story ■ ■ Homepage: https://canardia.com ■ Link to comment Share on other sites More sharing options...
Laurens Posted November 1, 2010 Author Share Posted November 1, 2010 Hi, Thanks for the replies all I have decided to take a stab at multithreading using the LE commands as I have taken special care not to call on entities or anything in both threads. I do have a problem connecting two hosts even though it looks like I'm doing everything just like in the example on the wiki yet none of the networking events ever trigger. Netwerks initializes just fine as well and turning of my (Windows) firewall does not make a difference. This is my server setting up the host and calling the Update method in a new thread. const bool Game::Initialize() { host = CreateHost(0, 7777); _beginthread(Game::Update, 0, reinterpret_cast<void*>(this)); return true; } This is the update method that should capture all networking events: void Game::Update() { while (true) { TEvent event; WaitNetEvent(host, &event); if (event.id == EVENT_CONNECT) { peers.push_back(event.source); } if (event.id == EVENT_PACKETRECEIVED) { // TODO } if (event.id == EVENT_DISCONNECT) { peers.remove(event.source); } } } This is the test code I use: THost client = CreateHost(0, 7778); TPeer server = ConnectHost(client, HostIp("127.0.0.1"), 7777); while (!AppTerminate() && !KeyHit()) { TPacket packet = CreatePacket(); WriteLine(packet, (byte*)"Hello world!"); SendPacket(client, server, packet); UpdateFramework(); RenderFramework(); Flip(); } Any clue as to what is wrong here? Many thanks! Quote Link to comment Share on other sites More sharing options...
Laurens Posted November 3, 2010 Author Share Posted November 3, 2010 Does anyone have a working C++ example? I am still stuck on this. Thanks! Quote Link to comment Share on other sites More sharing options...
Laurens Posted November 3, 2010 Author Share Posted November 3, 2010 I created a sample application which does not run on my computer but does seem to work for the example on the wiki. I would be very grateful if anyone could tell me if this is running for them, and even more grateful if anyone could tell me what I am doing wrong. Thanks! #include <process.h> #include "engine.h" #include "netwerks.h" bool keepRunning = true; THost host; void __cdecl Update(void* params) { while (keepRunning) { TEvent event; WaitNetEvent(host, &event); if (event.id == EVENT_CONNECT) { printf("Client connected."); } if (event.id == EVENT_PACKETRECEIVED) { printf("Packet received."); } if (event.id == EVENT_DISCONNECT) { printf("Client disconnected."); } } } int main() { InitializeNetwerks(); Initialize(); SetAppTitle("Game Code"); Graphics(1280, 800); CreateFramework(); host = CreateHost(); _beginthread(Update, 0, 0); THost client = CreateHost(0, 7778); TPeer server = ConnectHost(client, HostIp("127.0.0.1")); while (!AppTerminate() && !KeyHit()) { TPacket p = CreatePacket(); WriteLine(p, (byte*)"Hello world!"); SendPacket(client, server, p); UpdateFramework(); RenderFramework(); Flip(); } keepRunning = false; Terminate(); TerminateNetwerks(); return EXIT_SUCCESS; } Quote Link to comment Share on other sites More sharing options...
Chris Paulson Posted November 3, 2010 Share Posted November 3, 2010 LW is not thread safe so you need mutex's around sections of LW commands. Quote Link to comment Share on other sites More sharing options...
Laurens Posted November 3, 2010 Author Share Posted November 3, 2010 Wouldn't that only prevent a particular section of my[/code] to be thread safe? Say I make the entire Update method mutually exclusive. The first time the method is called it gets a lock. A second call would wait until the lock is released but I never make a second call to Update. Maybe I get how mutex' work wrong. If I encapsulate all LW calls in a mutex, would that prevent LW commands from getting called concurrently? If I have two threads executing a different method but still calling LW commands from those methods, wouldn't I still be calling LW methods concurrently, even if I surround those methods in a mutex. If the former is the case than I can never send a packet from the main loop and listen for incoming packets (WaitNetEvent) in a second thread, making the entire library useless. I think however that is not how it works. It would only prevent my code getting called twice which I am not doing anyway. Thanks for the response though! Quote Link to comment Share on other sites More sharing options...
Laurens Posted November 3, 2010 Author Share Posted November 3, 2010 I just tried the LUA example Josh posted on the Wiki by dragging server.lua and client.lua on engine.exe, only to get a "CreateHost: attempted to call a nill value" (or something of that sort). Is it safe to say networking is completely broken and I should file a bug report? Quote Link to comment Share on other sites More sharing options...
Rick Posted November 4, 2010 Share Posted November 4, 2010 I would say it's safe to say LE networking isn't the way to go. It doesn't meet the criteria of what a networking library should be. I know you want to make it fit, but cut your losses now and move on to another networking library Quote Link to comment Share on other sites More sharing options...
Chris Paulson Posted November 4, 2010 Share Posted November 4, 2010 Wouldn't that only prevent a particular section of my[/code] to be thread safe? Say I make the entire Update method mutually exclusive. The first time the method is called it gets a lock. A second call would wait until the lock is released but I never make a second call to Update. Maybe I get how mutex' work wrong. If I encapsulate all LW calls in a mutex, would that prevent LW commands from getting called concurrently? If I have two threads executing a different method but still calling LW commands from those methods, wouldn't I still be calling LW methods concurrently, even if I surround those methods in a mutex. If the former is the case than I can never send a packet from the main loop and listen for incoming packets (WaitNetEvent) in a second thread, making the entire library useless. I think however that is not how it works. It would only prevent my code getting called twice which I am not doing anyway. Thanks for the response though! Indeed - you can have no LW command issued in a thread while another LW is occurring in the main thread. You handle it this way:- mainLoop:- { gameLogic(with non LW commands) mutex(LW) { updateworld networkstuff renderworld } render none LW stuff flip } thread:- loop:- { non LW commands mutex(LW) { LW network commands - which cannot block or wait } sleep } Quote Link to comment Share on other sites More sharing options...
Laurens Posted November 4, 2010 Author Share Posted November 4, 2010 Just tried mutex' first. Same end-result sadly. I then even tried creating two projects, a server that purely listens and does nothing else LW related and a client that just connects, sends some data and disconnects, nothing else. Still the same result (that is no result). I used PortQryV2 to confirm that the port is actually open and it is, so CreateHost seems to work and I suspect the problem must be with ConnectHost. I am about to give up on this and switch to RakNet unless Josh could take a look at this and confirm whether it is truly a bug or not. Many thanks for the help everyone! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.