Blitzplay help

Blitz3D Forums/Blitz3D Programming/Blitzplay help

Farflame(Posted 2005) [#1]
This is specific to Blitzplay I think. I've tried emailing Surreal who created it but have had no reply, and can't get help on the Blitzcoder forums :(

Basically, I have a large server program that's doing alot of sending/receiving data using Blitzplay. It was working fine until recently when I was trying to send 192 strings from the server to the client. The strings were no more than 50 bytes, including the header information. I was sending using BP's reliable sending because I NEED all of the strings to get there.

It wasn't all arriving, so I wrote the details out to logs and found that exactly 11 of the strings were arriving each time. When I changed to non-reliable sending, all of them were arriving (mind you, this is between two computers linked via a router, so it's not so surprising), and when I changed to ordered sending, none of them arrived at all.

As I say, I need to have reliable messages, so I can't just switch to non-reliable ones, and I doubt they'd be that reliable on a real internet connection anyway.

What I'm confused about, is why exactly 11 would be arriving every time I test it. It's almost as if I've reached some kind of limit, yet when I test Blitzplay on a test program it seems quite happy to send endless amounts of data at almost any speed I ask of it (well, it's happy to be stuck in a continual sending/receiving loop).

Any ideas what might be causing this?


KuRiX(Posted 2005) [#2]
Here is your answer:

BlitzPlay uses an Ack ID for every reliable message, so until the message has not been correctly sent the Ack Id is no available again.

so if you send more than the maximum, the rest are ignored.

The solution is not easy. Increasing that maximum is impossible, cause it uses one byte (255 maximum).

Perhaps you should use TCP own sockets...


Farflame(Posted 2005) [#3]
How do you mean by TCP own sockets? Do you mean use Blitz's TCP commands, instead of using Blitzplay?

Also, what is the maximum number of messages I can send then? 255? Is this different with TCP?

Is there a detailed explanation of all of this somewhere? I feel like I'm programming in the dark here.


KuRiX(Posted 2005) [#4]
Well, the limit of 255 Max Reliable messages *at the same moment* is a limit of SurrealĄs DirectPlay Library.

He thought that no one would send 255 messages at the same time and when sending more, no one would have arrived.

TCP socket's don't have this problem, because it uses the windows socket library, that manages all of this.

There are a function in BlitzPlay that tells you how many free Ack Id's you have. Perhaps you should block all the sending until one Id is free.


Farflame(Posted 2005) [#5]
Yes, that sounds like a plan. I'll discuss it with Surreal aswell and hopefully I can edit my copy of the library or somethng. At least it looks like there are solutions, thanks :)


KuRiX(Posted 2005) [#6]
I have emailed Surreal with this problem some weeks ago, with no response. I am modifying this great library on my own, getting some interesting improvements.

Although i have not corrected that problem. What i do is sent all the "must arrive" messages with priority, sending them first, or reserving some ACK ID's.


Farflame(Posted 2005) [#7]
Yeah, he used to answer emails very quickly, but he seems to have disappeared off the face of the Earth lately.

Luckily, for this particular problem, I can get around it by sticking the strings together and parsing them at the client end. I'll just have to hope this problem of 255 max signals is fixed by the time I have 10,000 people playing my game :)


Farflame(Posted 2005) [#8]
Don't suppose you know how to use the BP_AckInUse function do you? I can't get it to work. My theory is to put the send message in a loop until the Ack reports false (i.e sent), but I'm doing something wrong. Could you tell me which part of this is wrong?

Repeat
AckID=BP_Message(p\net_ID,BP_Host_ID,2,packet$,BP_Ordered)
ID=BP_FindPlayersConn(p\net_ID)
Until BP_AckInUse(ID,AckID)=False



KuRiX(Posted 2005) [#9]
Of course. The function that sent the messages, check the ack's, etc, is BP_UPDATENETWORK. So if you don't call that function, you will never update the status of the variables.

Repeat
AckID=BP_Message(p\net_ID,BP_Host_ID,2,packet$,BP_Ordered)
ID=BP_FindPlayersConn(p\net_ID)
BP_UPDATENETWORK()
Until BP_AckInUse(ID,AckID)=False

Anyway, you are sending a message and waiting for its ack. This kind of protocol is called "Stop and Wait", so you only will send one message at a time, in a blocking way. Easy solution, but not too efficient.

P.D: Don't forget to check after that test the incoming messages that BP_UPDATENETWORK could have created...

The Best solution for Surreal would be to put the "not sent" messages in a queue until some Ack ID Slot is free. He uses types for the messages, so putting a new field called queueid should kick the problem. Then in every BP_UPDATENETWORK let's see if there is any unsent message due to insufficient ack id's.


Farflame(Posted 2005) [#10]
Yeah, I assumed it was a messy solution, but was wondering if it would work anyway. Joining the strings together has solved this main problem, but I hope that Surreal will fix this as I can envisage all sorts of problems if I had alot of players in my game.

By the way, I still get an error with that code above. On the line 'ID=BP_FindPlayersConn(p\net_ID) I get an 'Illegal Type Conversion' error. Where exactly do I get the ID from? Surely the net_ID in the players details is what it's after?


KuRiX(Posted 2005) [#11]
BP_FindPlayersConn returns a connection, not an ID.
Soy if ID is not of type BP_connection (i don't know only seeing the code above) you must:

Conn.BP_Connection = BP_FindPlayersConn(blablabla...


Farflame(Posted 2005) [#12]
I'm afraid I'm struggling with this. It has a problem with the p\net_ID I think. In my program, p\net_ID is created with this piece of code......

Case BP_PLAYERHASJOINED		;Someone joined!
p.pdata = New pdata		;Create a new player and initialize their data
p\net_id = msg\msgFrom


So is p\net_id not the correct variable to be feeding into BP_FindPlayerConn(?)?


KuRiX(Posted 2005) [#13]
Your above code is correct. So i don't know what is the problem...


Farflame(Posted 2005) [#14]
This may sound like a dumb question, but in the BP library itself, I see the lines.....

Field ACKbuffer.BP_ReliablePacket[255]

... a couple of times. If I just increased the 255 to say... 10,000, would that fix the problem mentioned above?


KuRiX(Posted 2005) [#15]
No, because later, when sending the messages, Surreal Uses only one byte of the udp message header containing the number of ID.

One Byte gives only 255 numbers, so...


Farflame(Posted 2005) [#16]
And there's no way to change that by altering the library itself? Is it something only Surreal could do?


KuRiX(Posted 2005) [#17]
Of course there is a way!. You could use more than one byte for the Ack Counter. The problem is that is a very internal check. For example, one reliable message would be like:

senderid,receiverid,ackid,msgtype,msgdata,timerid

senderid = one byte (by default)
receiverid = one byte(by default)
etc...

then, if you want to use two bytes for the ackid you must change all places where the message is parsed, telling them that there are N bytes for the Ack Id. Then you must change all the functions that returns the next free ack id, etc...

What i say is that this is a "relatively easy job" for Surreal. So why spend lot of hours changing it ourselves? I have made lot of changes to the library, but only easy things.

And of course, Surreal thought that you would have a limit anyway, so the user should check that. Although as i have commented before, the best solution is to put the "not free ack id" messages in a queue, then send them when possible. I think this is an easier solution...