GMS 2 Receiving packets properly from a Java server?

UPDATE:
I've determined that either Java is sending multiple messages at a time in one packet or GameMaker is receiving multiple packets but including them in one buffer in the Async Network event.
I don't know which and I'm currently not sure how to tell.

Each time I write a "message" from my Java server, I'm writing a buffer of 256 bytes. Sometimes GameMaker will see 256 bytes, sometimes it will see 512.
I could simply just read 256 bytes at a time, but I'd like to understand why multiple 256-byte messages are being received in one Async event. I'd also prefer to deal with one 256-byte message at a time instead of parsing through it in one event. Is this possible?

----

I'm trying to have my Java server send multiple packets at a time to GameMaker clients over TCP.

The problem is, sometimes when I send multiple packets at a time, not all of them go through:

Java:
// Send all player's information to everyone else
outerPlayerIter = players.iterator();
while(outerPlayerIter.hasNext()) {
    Player outerPlayer = outerPlayerIter.next();
      
    Iterator<Player> innerPlayerIter = players.iterator();
    while(innerPlayerIter.hasNext()) {
        Player innerPlayer = innerPlayerIter.next();
        boolean isYou = false;
        if(innerPlayer.equals(outerPlayer)) isYou = true;
        // Send innerPlayer's info to outerPlayer
        Thread.sleep(100);
        dataBuffer.clearBuffer();
        dataBuffer.writeByte(Msgs.mm_toclient.MES_SENDPLAYERINFO);
        dataBuffer.writeBool(isYou);
        dataBuffer.writeBool(innerPlayer.getIsHost());
        dataBuffer.writeString(innerPlayer.getName());
        dataBuffer.writeString(innerPlayer.getPublicIP().getHostAddress());
        dataBuffer.writeShort((short)innerPlayer.getUdpPort());
        outerPlayer.getSocket().getOutputStream().write(dataBuffer.getByteArray());
        outerPlayer.getSocket().getOutputStream().flush();
    }
  
}
The only way I've managed to get all my messages through on GM is to sleep the thread for 100 milliseconds.

I don't know why sleeping the thread is the only way to get all packets received by my GameMaker client's.

Am I doing something wrong?
 
Last edited:

chamaeleon

Member
Am I doing something wrong?
Perhaps not on the Java side. Showing the async event code on the GMS side would be helpful. As a first guess, I imagine it is possible you do not consume all the content in the data buffer, assuming one invocation of the event corresponds to one packet/message. In other words, you may be throwing away the data you think you didn't receive. Start off with checking the size with the buffer compared with how much data you read out to verify whether this is the problem, perhaps.
 
Perhaps not on the Java side. Showing the async event code on the GMS side would be helpful. As a first guess, I imagine it is possible you do not consume all the content in the data buffer, assuming one invocation of the event corresponds to one packet/message. In other words, you may be throwing away the data you think you didn't receive. Start off with checking the size with the buffer compared with how much data you read out to verify whether this is the problem, perhaps.
Okay so, on my Java side the buffer size I've allocated per message is 256 bytes (every time I write to the output stream I'm writing 256 bytes)

In the Async Network event on GameMaker, sometimes the buffer will be 256 bytes, other times it will be 512, it appears to be random.
If I sleep a significant amount of time between writing messages to the OutputStream in Java, the buffer will be 256 bytes on GameMaker's network event.

I read the bytes in the buffer in the event, and they appear to be correct.

So it seems GameMaker is tackling multiple messages in one Async Network step.

Is there a way to prevent GameMaker from doing this? Or is it something Java is doing?

I'd prefer to deal with each "message" separately in its own step in the async network event rather than parsing each multiple of 256 bytes each time. Is this possible?
 

Padouk

Member
Yeah it's neither a GMS nor a Java issue. It's a TCP feature...

Quoting the first paragraph from: https://blog.stephencleary.com/2009/04/message-framing.html

One of the most common beginner mistakes for people designing protocols for TCP/IP is that they assume that message boundaries are preserved. For example, they assume a single “Send” will result in a single “Receive”.

Some TCP/IP documentation is partially to blame. Many people read about how TCP/IP preserves packets - splitting them up when necessary and re-ordering and re-assembling them on the receiving side. This is perfectly true; however, a single “Send” does not send a single packet.
[...]
First, one must understand the abstraction of TCP/IP. From the application’s perspective, TCP operates on streams of data, never packets. Repeat this mantra three times: “TCP does not operate on packets of data. TCP operates on streams of data.”
Few notes for you
A) Maybe that 256+256 happens on the server side. Regardless of your "flush" there's the nagle algorithm (usually enabled by default) that could be kicking it, grouping sends to reduce bandwidth.
B) Maybe that 256+256 happens on the client side. Few various reasons.. delays, packets retry, etc. The underlying network will feed your GMS stream with everything that was sent and in the right order.

Best for you is probably to expect an arbitrary number of messages per Async Network.
 
Top