Network multithreading

I program an online game for two reasons: one, to get to know server / client requests in real time (unlike a regular web browser that is not in real time), and actually get my hands wet in this area, therefore, I can begin to create it correctly.

Anywho, I do this in C ++, and I use winsock to handle basic basic network tests. I obviously want to use framelimiter and have 3D output, and all this at some point, and my main problem is that when I execute the send () or receive () function, the program kindly stands there and waits for an answer . This can lead to 8 fps even with the best internet connection.

Thus, the obvious solution for me is to get the network code out of the main process and start it in its thread. Ideally, I would call “send” in my main process, which would send a pointer to a message to the network stream and then periodically (every frame) to check if the network stream received a response or timeout, or what you have. In an ideal world, I would actually have two or more network streams working at the same time, so that I could say that I launched the chat window and performed background download of part of the armor and still let the player run around right away.

The main problem is that for me this is a new business. I understand the concept of streaming, but I see some serious problems, for example, what happens if two streams try to read and write the same memory address at the same time, etc. I know that methods already exist for processing this type, that I am looking for suggestions on the best way to implement something like this. Basically, I need thread A to be able to start a process on thread B, sending a piece of data, the polling status of a B stream, and then getting a response, like a piece of data., Ideally, without any major glitches. ^ _ ^ I will worry about what actually contains this data, and how to process dropped packets, etc. Later I just need to do this first.

Thanks for any help / advice.

PS: Just thought about it, it might make the question easier. Is there a way to use the Windows event processing system to my advantage? For example, is it possible for thread A to initialize data somewhere, then fire an event in thread B to receive data, and vice versa for thread B to tell thread A that it was done? This will probably solve many of my problems, since I really do not need both threads to be able to work with data at the same time. I just don't know if this is possible between two different threads. (I know that a single thread can create its own messages for an event handler.)

+4
source share
6 answers

Easiest

so that you can do this, just call the Windows QueueUserWorkItem API. All you need to specify is the function that the stream will execute and the input passed to it. The thread pool will be automatically created for you and the tasks that are performed in it. New threads will be created as needed.

http://msdn.microsoft.com/en-us/library/ms684957(VS.85).aspx

More control

You can have more granular control using a different set of APIs that can again manage the thread pool for you -

http://msdn.microsoft.com/en-us/library/ms686980(VS.85).aspx

Do it yourself

If you want to control all aspects of creating threads and managing pools, you will have to create threads yourself, decide how they should end, how much to create, etc. (beginthreadex is the api you should use to create threads. If you use MFC, you must use the AfxBeginThread function).

Submitting Jobs to Workflows - When Port Entry is Complete

In this case, you also have to worry about how to report your assignments - I would recommend IoCOmpletionPorts to do this. This is the most scalable notification mechanism that I currently know for this purpose. It has the added advantage that it is implemented in the core, so you avoid all kinds of dead silos that you will encounter if you decide to do something yourself.

In this article you will learn how with code samples -

http://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx

Report otherwise - Windows Messages

You can use Windows messages to pass status back to the parent stream, since it is still waiting for the message. use the PostMessage function to do this. (and check for errors)

ps: you can also highlight the data that should be sent by the selected pointer, and then the workflow can take care of deleting it after sending it. This way you also avoid the back pointer.

+7
source

BlodBath's suggestion of non-blocking sockets is potentially the right approach.

If you are trying to avoid using a multi-threaded approach, you can explore the use of I / O overlap settings on your sockets. They will not be blocked when you send or receive, but they have an additional bonus, giving you the opportunity to wait for several events in your single event cycle. When your transfer is over, you will receive an event. (see this for some details)

This is incompatible with the multi-threaded approach, so there is an opportunity to change your mind later .; -)

About the design of your multi-threaded application. the best thing to do is work out all the external actions that you want to pay attention to. For example, so far in your question you have indicated network transmissions, network retrieval and user activity. Depending on the number of concurrent connections you will be dealing with, you will probably find that it is conceptually easier to have a thread on a socket (assuming a small number of sockets), where each thread is responsible for all the processing for that socket.

You can then implement some form of messaging between your streams, as RC recommended. Position your system so that when you send a message to a specific thread, the event is also dispatched. Then your threads can be sent waiting for one of these events. (as well as any other events related to the stimulus, user events, etc.).

You are absolutely right that you need to be careful in situations where more than one thread is trying to access the same part of memory. Mutexes and semaphores are what you can use there.

Also keep in mind the limitations your gui has when it comes to multithreading. Some discussion on this issue can be found in this issue . But the shortened version is that most (and Windows is one of them) GUIs do not allow multiple threads to perform operations with the graphical interface at the same time. To work around this problem, you can use the message pump in your application by sending custom messages to your gui thread to force it to perform gui operations.

+3
source

I suggest looking for non-blocking sockets for a quick fix. Using non-blocking sockets send () and recv () are not blocked, and with the select () function you can receive any pending data in each frame.

+2
source

See how the producer-consumer problem is : upon receipt, your network communication stream is the producer, while the user interface stream is the consumer. When sending, it's just the opposite. Implement a simple buffer class that gives you methods like push and pop (pop should block for a network stream and not block for a user interface stream).

Instead of using the Windows event system, I would prefer a more portable one, like Boost state variables .

0
source

I do not code games, but I used a system similar to the one suggested by pukku. This is good for doing things like having a buffer priority to process your messages, if you have such a need.

I think of them as mailboxes per stream. Do you want to send a package? Ask ProcessThread to create a “thread message” with a payload to go to the wire and “send” it to NetworkThread (that is, click it in the NetworkThread queue / mailbox and pass the NetworkThread state variable so that it wakes up and pull it out). When NetworkThread receives the response, pack it into the thread message and send it back to ProcessThread in the same way. The difference is that ProcessThread will not be blocked under the condition variable, just by polling by mailbox.empty () when you want to check the answer.

You might want to directly click and place, but a more convenient way for large projects is to implement the toThreadName, fromThreadName scheme in the ThreadMsg base class and the mail branch in which threads register their mailbox. Then PostOffice sends (ThreadMsg *); A function that receives / pushes messages to the appropriate mailbox based on both. The mailbox (class buffer / queue) contains ThreadMsg * = receiveMessage (), basically removing it from the main queue.

Depending on your needs, you can have ThreadMsg containing the process of the virtual function (..), which can be redefined accordingly in the derived classes or just have the usual ThreadMessage class with from, from and getPayload () functions to return the original data and process it directly in ProcessThread.

Hope this helps.

0
source

Some topics that may interest you:

  • mutex : mutex allows you to block access to certain resources for only one thread

  • semaphore . A method for determining the number of users of a particular resource (= how many threads access it) and a method for accessing threads to a resource. Mutex is a special case of a semaphore.

  • critical section : a mutex-protected piece of code (a street with one lane) that can only be moved one stream at a time.

  • Message Queue: A method for distributing messages in a centralized queue

  • interprocess communication (IPC) is a method of threads and processes for communicating with each other through named pipes, shared memory and many other methods (this is more a concept than a special technique)

All topics in bold can be easily found in the search engine.

0
source

Source: https://habr.com/ru/post/1277245/


All Articles