http://qs321.pair.com?node_id=377244

BUU has asked for the wisdom of the Perl Monks concerning the following question:

First off, a quick summary of the situation and current design. I have a "bot" that connects to a chat network, sort of like IRC. After I send the connection and auth data and so forth, I then go to a loop that waits for packets from the chat server. When it receives a packet, it decodes it and does the appropiate thing, which is most often calling a subroutine that does stuff then returns.

My problem is, in one of these callbacks I want to get some more data from the network and do stuff based on it. The call back itself can easily send the request for data, but how does it get it back? My problem is that the packet that responds the request isn't guaranteed, or even likely to by the next packet, or the packet after that for that matter, and of course those packets that aren't a direct response to my request need to be processed by my main loop. So thats my design question, how can I do the appropiate thing with the response?
  • Comment on Design decision, call backs and network data

Replies are listed 'Best First'.
Re: Design decision, call backs and network data
by Fletch (Bishop) on Jul 25, 2004 at 12:10 UTC

    Use POE! It's meant for this kind of event driven programming. You fire off whatever request to get more info and note in your instance that you're waiting on requested information. Your got_traffic callback checks if you're expecting something or not when it receives a reply. You could even setup an alarm event that clears that state if you don't get a reply back after however long.

      Could you perhaps elaborate a bit? How would poe, and more specifically my "got_traffic" call back route the data, even if it knew I was requesting a response? What I have now I could just set a variable or object from my call back that says "requesting response", I'm just not sure what to do with the response.

        One way would be to create a separate session which handles (making something up here) "administrative requests". You specify that this session is in charge of sending and receiving any such requests. The main code posts a "get_frobnitz" event to the admin session. The admin session formulates and sends whatever request back through the communications handling session (or writes it directly to the socket's wheel). When the reply comes back an event's posted to the admin session which parses and handles it. The admin session could store the results in a shared location, or fire off another event (got_frobnitz) back to the original caller.

        At any rate take a look at any of the IRC related components and bots, as I'm sure they'd give you a better idea than my vague verbal handwaving above. :)

        • IRC Bots
        • Distributing Events, which might be of use (create a temporary handler which handles the returned data, and your communications handler fires it back when the reply is received).
Re: Design decision, call backs and network data
by beable (Friar) on Jul 25, 2004 at 08:26 UTC

    I think you'll have to add code to your main loop to handle the packet when it comes in, and pass it off to the subroutine that can deal with it. Here's some pseudocode:

    The implementation details are left as an exercise for the reader.

Re: Design decision, call backs and network data
by zentara (Archbishop) on Jul 25, 2004 at 12:27 UTC
    I can sympathize with your current problem. I'm working on a 4 player, tcp-networked game and have spent the last 4 days trying to solve a similar problem. If the "listening loop' isn't setup just right, things quickly get "out of synchronization" and I end up with a situation where clients have to hit enter a few times, to be brougt back into "sync".

    All I can say is setup a test network, and hack,hack,hack :-) Sooner or later you will find the right place to put the update code. In my situation, I've resorted to "tagging" the data being sent from the server, with "to_all", or to "$player_only", and have the client's listening loop filter it accordingly.

    I have found this quite difficult to get a handle on, because of the complexity of remembering that the callbacks in the server are "client specific", and it's real easy to think the data is being broadcast, when in actuality it's only going to 1 client. And the inverse problem, when you want to broadcast to everyone, but the last-client to send, gets the data twice, because you happen to be in it's client specific callback. The worst problem being your brain gets "numbed" by trying to absorb it all, and you can easily "get on a wrong track".

    So setup a local IRC server, and a few test clients, and start trying different code. Evertime you reach a point, where things seem to be working, save a backup of the code, so you can revert to it, if your attempt at the next step, proves a dead-end.


    I'm not really a human, but I play one on earth. flash japh
Re: Design decision, call backs and network data
by ysth (Canon) on Jul 25, 2004 at 19:40 UTC
    Depends on how much context you need to deal with the response. For maximum flexibility, have your "things pending responses" variable be an array of coderefs, where for each incoming packet, each coderef is called in turn until one returns true indicating that it handled the packet. Then a callback can push an anonymous closure onto the array with whatever context it needs. If a response is always going to be a single packet, it probably makes most sense for the main loop's loop through the array to remove the coderef that handled the packet; if not, the pushed coderef itself should when it's received all of its response.
Re: Design decision, call backs and network data
by pg (Canon) on Jul 25, 2004 at 16:48 UTC

    The question is a bit vague, but sounds like sort of difficulty to deal with multiple network connections. IO::Select is almost the easiest way to deal with connections with multiple sources. Take a look at the documentation, play with it, and you may come back with more specific questions.

      I'm not really sure how you got that impression, as theres only one network connection. On this network connection the server sends me events and such like that happen on the server. It also sends me responses to specific commands. My problem is that when I send a command to the server, I want to do something with the response, but I don't know when the response will be sent back, as the server might send back some events before the response. The place I send the request however, is in a call back for a specific packet type, so it can't handle other event packets. My question, is how do I deal with the event packets being sent back before my request response? Ignoring them isn't an option really.