Delphi and Kylix

Moderators: pritaeas
Number of threads: 7232
Number of posts: 19038

This Forum Only
Post New Thread
Single Post View       Linear View       Threaded View      f

Report
TCP/IP : Sending binary commands Posted by porodoro on 17 Aug 2007 at 9:31 AM
Hello.
I have created a very simple sdl game , and im trying to add multiplayer mode.
Im using delphi for the server(much easier than c++) , and so far , i was sending the commands like this for example(simple text):

"[movePlayer ID,x,y end]"


This method is the worst. So could someone tell me how to send commands in binary format ?(its the fastest way)

Thanks.
Report
Re: TCP/IP : Sending binary commands Posted by zibadian on 17 Aug 2007 at 12:28 PM
: Hello.
: I have created a very simple sdl game , and im trying to add
: multiplayer mode.
: Im using delphi for the server(much easier than c++) , and so far ,
: i was sending the commands like this for example(simple text):
:
:
: "[movePlayer ID,x,y end]"
:
:
: This method is the worst. So could someone tell me how to send
: commands in binary format ?(its the fastest way)
:
: Thanks.
The easiest way is to create a record and send that. For example:
type
  TCommand = record
    CommandID: integer;
    PlayerID: integer;
    ParamSize: integer;
  end;

  TMoveCommand = record
    X, Y: integer;
  end;

procedure SendMove(PlayerID, X, Y: integer);
var
  Command: TCommand;
  MoveCommand: TMoveCommand;
begin
  Command.CommandID := SOME_ARBRITRARY_COMMAND_ID;
  Command.PlayerID := PlayerID;
  Command.ParamSize := SizeOf(MoveCommand);
  MoveCommand.X := X;
  MoveCommand.Y := Y;
  SendBinaryData(Command, @MoveCommand);
end;

procedure SendBinaryData(Command: TCommand; Params: pointer);
begin
  // SendMemory(@Command, SizeOf(Command));
  if Params <> nil then
    // SendMemory(Params, Command.ParamSize);
end;

The SendMemory() depends on the implementation of your communication. It simply sends a block of memory, pointed to by first parameter, with the size indicated by the second parameter.
At the receiving end, you just read the TCommand record. If the ParamSize is not 0, then you read upto ParamSize of data into some allocated space. Then you can typecast it into a record based on the CommandID and then execute the command.
Report
Re: TCP/IP : Sending binary commands Posted by porodoro on 17 Aug 2007 at 9:14 PM
: : Hello.
: : I have created a very simple sdl game , and im trying to add
: : multiplayer mode.
: : Im using delphi for the server(much easier than c++) , and so far ,
: : i was sending the commands like this for example(simple text):
: :
: :
: : "[movePlayer ID,x,y end]"
: :
: :
: : This method is the worst. So could someone tell me how to send
: : commands in binary format ?(its the fastest way)
: :
: : Thanks.
: The easiest way is to create a record and send that. For example:
:
: 
: type
:   TCommand = record
:     CommandID: integer;
:     PlayerID: integer;
:     ParamSize: integer;
:   end;
: 
:   TMoveCommand = record
:     X, Y: integer;
:   end;
: 
: procedure SendMove(PlayerID, X, Y: integer);
: var
:   Command: TCommand;
:   MoveCommand: TMoveCommand;
: begin
:   Command.CommandID := SOME_ARBRITRARY_COMMAND_ID;
:   Command.PlayerID := PlayerID;
:   Command.ParamSize := SizeOf(MoveCommand);
:   MoveCommand.X := X;
:   MoveCommand.Y := Y;
:   SendBinaryData(Command, @MoveCommand);
: end;
: 
: procedure SendBinaryData(Command: TCommand; Params: pointer);
: begin
:   // SendMemory(@Command, SizeOf(Command));
:   if Params <> nil then
:     // SendMemory(Params, Command.ParamSize);
: end;
: 
:
: The SendMemory() depends on the implementation of your
: communication. It simply sends a block of memory, pointed to by
: first parameter, with the size indicated by the second parameter.
: At the receiving end, you just read the TCommand record. If the
: ParamSize is not 0, then you read upto ParamSize of data into some
: allocated space. Then you can typecast it into a record based on the
: CommandID and then execute the command.

Nice , really nice.
But let me ask you two more questions!
1) Im working with indy components.
Which function should i use to send the memory block?
WriteBuffer(const abuffer,BYTES:integer); will work?

2) Is it wise to let the server handle information for the player?
such as HP/Ammo etc?
Or it will slow down the server?
Im asking because there are so many cheat editors that really, you cant
trust client...
Report
Re: TCP/IP : Sending binary commands Posted by zibadian on 19 Aug 2007 at 8:48 AM
: : : Hello.
: : : I have created a very simple sdl game , and im trying to add
: : : multiplayer mode.
: : : Im using delphi for the server(much easier than c++) , and so far ,
: : : i was sending the commands like this for example(simple text):
: : :
: : :
: : : "[movePlayer ID,x,y end]"
: : :
: : :
: : : This method is the worst. So could someone tell me how to send
: : : commands in binary format ?(its the fastest way)
: : :
: : : Thanks.
: : The easiest way is to create a record and send that. For example:
: :
: : 
: : type
: :   TCommand = record
: :     CommandID: integer;
: :     PlayerID: integer;
: :     ParamSize: integer;
: :   end;
: : 
: :   TMoveCommand = record
: :     X, Y: integer;
: :   end;
: : 
: : procedure SendMove(PlayerID, X, Y: integer);
: : var
: :   Command: TCommand;
: :   MoveCommand: TMoveCommand;
: : begin
: :   Command.CommandID := SOME_ARBRITRARY_COMMAND_ID;
: :   Command.PlayerID := PlayerID;
: :   Command.ParamSize := SizeOf(MoveCommand);
: :   MoveCommand.X := X;
: :   MoveCommand.Y := Y;
: :   SendBinaryData(Command, @MoveCommand);
: : end;
: : 
: : procedure SendBinaryData(Command: TCommand; Params: pointer);
: : begin
: :   // SendMemory(@Command, SizeOf(Command));
: :   if Params <> nil then
: :     // SendMemory(Params, Command.ParamSize);
: : end;
: : 
: :
: : The SendMemory() depends on the implementation of your
: : communication. It simply sends a block of memory, pointed to by
: : first parameter, with the size indicated by the second parameter.
: : At the receiving end, you just read the TCommand record. If the
: : ParamSize is not 0, then you read upto ParamSize of data into some
: : allocated space. Then you can typecast it into a record based on the
: : CommandID and then execute the command.
:
: Nice , really nice.
: But let me ask you two more questions!
: 1) Im working with indy components.
: Which function should i use to send the memory block?
: WriteBuffer(const abuffer,BYTES:integer); will work?
:
: 2) Is it wise to let the server handle information for the player?
: such as HP/Ammo etc?
: Or it will slow down the server?
: Im asking because there are so many cheat editors that really, you
: cant
: trust client...
1) I'm not sure, because I never worked with the indy components. WriteBuffer() sounds like the right function for it.

2) Everything the server needs to do will slow it down, which means that handling HP/ammo etc. will slow the server down slightly. Unless you're expecting a few 100,000 players to start with, the HP/ammo handling won't slow down the server too much. The gain of not being able to cheat is greater than the loss. I would recommend to let the server handle the player information.
Report
Re: TCP/IP : Sending binary commands Posted by porodoro on 28 Aug 2007 at 12:28 AM

[EDITED] : I Solved the first problem :!!!

Im back!(i was on vacation).

I have some more questions , please , if you can help do it!

1)I tried to setup a test server&client(in delphi) , and here's what i've got so far:

Note: im using delphi's sockets...
Packet class:

//=================
type tNETPACKET=record
     commandID:integer;
     commandSTR:string;
end;
//=================

//Send memory (client)
  procedure tform1.senddata(cmd:integer;cmdstr:string);
var PACKET:TNETPACKET;
  begin
   PACKET.commandID:=cmd;
   PACKET.commandSTR:=cmdstr;
   cl.socket.SendBuf(PACKET,sizeof(packet));
   end;

//receieve memory (server)
//NOTE: RCPACK = tNETPACKET CLASS
procedure TForm1.SOCKETClientRead(Sender: TObject;
  Socket: TCustomWinSocket);
  var i:integer;
  begin
  //clear
rcPACK.commandID:=-1;
rcPACK.commandSTR:='';
//get the length and fill the class
i:=socket.ReceiveLength;
socket.ReceiveBuf(rcPACK,i);
//showmessage(INTTOSTr(i));
//test command '444'. print the message..
if (rcpack.commandID=444) then
showmessage((rcpack.commandstr));
end;


The above code returns an empty string("commandstr") , but the weird thing is , that the "commandID"(int) value is correct.

Also , if i send more than one command the server crashes(returns error : external exception 800[more 0's]1).

2)Another thing.
The (real) client is written in C++.
All i have to do is to send the class?
my class looks like this:

class gameobject
{
protected:
DATA[8];//health,x,y,w,h etc..

public:
gameobject();
~gameobject();
//more functions..
};
Report
Re: TCP/IP : Sending binary commands Posted by zibadian on 28 Aug 2007 at 10:00 AM
:
: [EDITED] : I Solved the first problem
: :!!!

:
: Im back!(i was on vacation).
:
: I have some more questions , please , if you can help do it!
:
: 1)I tried to setup a test server&client(in delphi) , and here's what
: i've got so far:
:
: Note: im using delphi's sockets...
: Packet class:
:
:
: //=================
: type tNETPACKET=record
:      commandID:integer;
:      commandSTR:string;
: end;
: //=================
: 
: //Send memory (client)
:   procedure tform1.senddata(cmd:integer;cmdstr:string);
: var PACKET:TNETPACKET;
:   begin
:    PACKET.commandID:=cmd;
:    PACKET.commandSTR:=cmdstr;
:    cl.socket.SendBuf(PACKET,sizeof(packet));
:    end;
: 
: //receieve memory (server)
: //NOTE: RCPACK = tNETPACKET CLASS
: procedure TForm1.SOCKETClientRead(Sender: TObject;
:   Socket: TCustomWinSocket);
:   var i:integer;
:   begin
:   //clear
: rcPACK.commandID:=-1;
: rcPACK.commandSTR:='';
: //get the length and fill the class
: i:=socket.ReceiveLength;
: socket.ReceiveBuf(rcPACK,i);
: //showmessage(INTTOSTr(i));
: //test command '444'. print the message..
: if (rcpack.commandID=444) then
: showmessage((rcpack.commandstr));
: end;
:
:
: The above code returns an empty string("commandstr") , but the weird
: thing is , that the "commandID"(int) value is correct.
:
: Also , if i send more than one command the server crashes(returns
: error : external exception 800[more 0's]1).
:
: 2)Another thing.
: The (real) client is written in C++.
: All i have to do is to send the class?
: my class looks like this:
:
:
: 
: class gameobject
: {
: protected:
: DATA[8];//health,x,y,w,h etc..
: 
: public:
: gameobject();
: ~gameobject();
: //more functions..
: };
: 
:
Delphi strings are very complex entities. They are in essence a reference counted, copy-on-change, PChar typed variable. Sending them requires some special coding. If your commands are never longer than 255 characters, I would suggest to change them into shortstrings. Those are simply an array[0..255] of char, where the 0-th char holds the length.
If the commands can be longer than 255 characters, you first need to send the length (as integer), and then send all the bytes. The receiving end should read the length and then make a buffer as large as necessary to retrieve the string-data.
In code:
  socket.ReceiveBuf(l, SizeOf(integer));
  SetLength(CommandStr, l);
  socket.ReceiveBuf(CommandStr[1], l);

Report
Re: TCP/IP : Sending binary commands Posted by porodoro on 29 Aug 2007 at 1:09 PM
: :
: : [EDITED] : I Solved the first problem
: : :!!!

: :
: : Im back!(i was on vacation).
: :
: : I have some more questions , please , if you can help do it!
: :
: : 1)I tried to setup a test server&client(in delphi) , and here's what
: : i've got so far:
: :
: : Note: im using delphi's sockets...
: : Packet class:
: :
: :
: : //=================
: : type tNETPACKET=record
: :      commandID:integer;
: :      commandSTR:string;
: : end;
: : //=================
: : 
: : //Send memory (client)
: :   procedure tform1.senddata(cmd:integer;cmdstr:string);
: : var PACKET:TNETPACKET;
: :   begin
: :    PACKET.commandID:=cmd;
: :    PACKET.commandSTR:=cmdstr;
: :    cl.socket.SendBuf(PACKET,sizeof(packet));
: :    end;
: : 
: : //receieve memory (server)
: : //NOTE: RCPACK = tNETPACKET CLASS
: : procedure TForm1.SOCKETClientRead(Sender: TObject;
: :   Socket: TCustomWinSocket);
: :   var i:integer;
: :   begin
: :   //clear
: : rcPACK.commandID:=-1;
: : rcPACK.commandSTR:='';
: : //get the length and fill the class
: : i:=socket.ReceiveLength;
: : socket.ReceiveBuf(rcPACK,i);
: : //showmessage(INTTOSTr(i));
: : //test command '444'. print the message..
: : if (rcpack.commandID=444) then
: : showmessage((rcpack.commandstr));
: : end;
: :
: :
: : The above code returns an empty string("commandstr") , but the weird
: : thing is , that the "commandID"(int) value is correct.
: :
: : Also , if i send more than one command the server crashes(returns
: : error : external exception 800[more 0's]1).
: :
: : 2)Another thing.
: : The (real) client is written in C++.
: : All i have to do is to send the class?
: : my class looks like this:
: :
: :
: : 
: : class gameobject
: : {
: : protected:
: : DATA[8];//health,x,y,w,h etc..
: : 
: : public:
: : gameobject();
: : ~gameobject();
: : //more functions..
: : };
: : 
: :
: Delphi strings are very complex entities. They are in essence a
: reference counted, copy-on-change, PChar typed variable. Sending
: them requires some special coding. If your commands are never longer
: than 255 characters, I would suggest to change them into
: shortstrings. Those are simply an array[0..255] of char, where the
: 0-th char holds the length.
: If the commands can be longer than 255 characters, you first need to
: send the length (as integer), and then send all the bytes. The
: receiving end should read the length and then make a buffer as large
: as necessary to retrieve the string-data.
: In code:
:
: 
:   socket.ReceiveBuf(l, SizeOf(integer));
:   SetLength(CommandStr, l);
:   socket.ReceiveBuf(CommandStr[1], l);
: 
:
:
Thanks zibadian.
Even if i program in delphi for 1 year(or so)...still im learning new things...



 

Recent Jobs

Official Programmer's Heaven Blogs
Web Hosting | Browser and Social Games | Gadgets

Popular resources on Programmersheaven.com
Assembly | Basic | C | C# | C++ | Delphi | Flash | Java | JavaScript | Pascal | Perl | PHP | Python | Ruby | Visual Basic
© Copyright 2011 Programmersheaven.com - All rights reserved.
Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
Operated by CommunityHeaven, a BootstrapLabs company.