[WIP] Multiplayer Tic Tac Toe Tutorials 1-26-15

The Partridge Family were neither partridges nor a family. Discuss.
MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by MrGodin » January 27th, 2015, 12:29 am

Hi, i was looking at everything and starting trying things.
I was curious about the strings. Are they used to have an undefined string size ?.
i found if you hard set an array of chars ie: char str[255] , you can fill it and send it as in ints and floats ect.
I tried this and it worked fine with just filling an array without strings
struct FLOATPLAYERMOVESTRUCT
{
int type;
char str[256];
float px;
float py;
float pz;
FLOATPLAYERMOVESTRUCT(float ix, float iy, float iz,char* istr)
{
type = TYPE_PLAYERMOVE;
strcpy(str, istr);
px = ix;
py = iy;
pz = iz;
}
FLOATPLAYERMOVESTRUCT()
{
type = TYPE_PLAYERMOVE;
px = py = pz = 0.0f;
strcpy(str,"\0");
}
};

So i am assuming you're using strings for a non fixed size ?.
Curiosity killed the cat, satisfaction brought him back

MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by MrGodin » January 27th, 2015, 12:33 am

I sent this in the Game
FLOATPLAYERMOVESTRUCT PlayerMove(x, 20.0f, 100.0f,"This works ");
Client.SendData((char*)&PlayerMove, sizeof(FLOATPLAYERMOVESTRUCT));
ConnectionText += "Sent Data \n";


I then did this in the server to see ..
FLOATPLAYERMOVESTRUCT PlayerMove;
RecvCheck = MyPindroughtNetwork->ReceiveAndFillStructure(ID, (char*)&PlayerMove, sizeof(FLOATPLAYERMOVESTRUCT)); //Receive the packet from the client for game to join information
char x[256];
sprintf_s(x,"%0.2f",PlayerMove.px);
char y[256];
sprintf_s(y, "%0.2f", PlayerMove.py);
char z[256];
sprintf_s(z, "%0.2f", PlayerMove.pz);
cout << "Position Coords " << x << " : " << y << " : " << z << " " <<PlayerMove.str<<"\n";

and it displayed fine ..
Curiosity killed the cat, satisfaction brought him back

Pindrought
Posts: 432
Joined: September 26th, 2013, 4:57 pm
Location: Kentucky
Contact:

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by Pindrought » January 27th, 2015, 2:09 am

MrGodin wrote:I sent this in the Game
FLOATPLAYERMOVESTRUCT PlayerMove(x, 20.0f, 100.0f,"This works ");
Client.SendData((char*)&PlayerMove, sizeof(FLOATPLAYERMOVESTRUCT));
ConnectionText += "Sent Data \n";


I then did this in the server to see ..
FLOATPLAYERMOVESTRUCT PlayerMove;
RecvCheck = MyPindroughtNetwork->ReceiveAndFillStructure(ID, (char*)&PlayerMove, sizeof(FLOATPLAYERMOVESTRUCT)); //Receive the packet from the client for game to join information
char x[256];
sprintf_s(x,"%0.2f",PlayerMove.px);
char y[256];
sprintf_s(y, "%0.2f", PlayerMove.py);
char z[256];
sprintf_s(z, "%0.2f", PlayerMove.pz);
cout << "Position Coords " << x << " : " << y << " : " << z << " " <<PlayerMove.str<<"\n";

and it displayed fine ..

You can do it that way, but there are a few issues with doing it this way.

First Issue - I don't know why, but for some reason you are allocating a 256 byte char array for your x/y/z to print them out. I would've set up the code differently. (I'll post at the bottom how I would've done it.) There is no reason to have

Code: Select all

char x[256], y[256], z[256];
It's just allocating 768 bytes for no reason.


Also, yes you can have a

Code: Select all

char string[256];
in your struct if you want to send a string that way, but there are a few major issues with this.

The first issue is every successful packet you are wasting allocated memory/bandwidth sending empty bytes/not using all of the bytes. This is not true if you are using all 256 bytes with every packet, but I can't think of how you would have it set up where that would be the case.

Think of it like this.

You sent the message "This works " which is a total of 11 characters including the space at the end (not including null terminator).

So in sending this packet, we have sent 1 int for the type (4 bytes), 3 floats (4 bytes each), and a char array of size 256 (256 bytes) for a total of (3*4 + 256) = 272 bytes.

The issue is we sent 255 unused bytes in our char array. It's just sending blank data.


Alternatively, if we had used a string, with the way the SendDataStructureWithStrings and ReceiveDataStructureWithStrings are set up, we would have only sent 1 int (4 bytes), 3 floats (3*4 = 12 bytes), an integer for the string size (4bytes), the characters in the string (11 bytes) for a total of (4+12+4+11) = 31 bytes. Not only are we sending less bytes, but if we need to send a message larger than 256 bytes, it will not be an issue since we're using a string which is resizable.


Here is how I would've set it up to have the same functionality as yours, but using less resources.
Note: Strings are always at the end in data structures for the way the framework is set up to handle them.

Code: Select all

struct FLOATPLAYERMOVESTRUCT
{
int type;
float px;
float py;
float pz;
string str;
FLOATPLAYERMOVESTRUCT(float ix, float iy, float iz,string istr)
{
type = TYPE_PLAYERMOVE;
str = istr;
px = ix;
py = iy;
pz = iz;
}
FLOATPLAYERMOVESTRUCT()
{
type = TYPE_PLAYERMOVE;
px = py = pz = 0.0f;
str = "";
}
};
In the game we'd do

Code: Select all

FLOATPLAYERMOVESTRUCT PlayerMove(x, 20.0f, 100.0f,"This works ");
Client.SendDataStructureWithStrings(1, (char*)&PlayerMove, &PlayerMove.str);
ConnectionText += "Sent Data \n";
In the server we'd have

Code: Select all

FLOATPLAYERMOVESTRUCT PlayerMove;
RecvCheck = MyPindroughtNetwork->ReceiveAndFillStructureWithStrings(ID, 1, (char*)&PlayerMove, &PlayerMove.str); //Get packet that contains 1 string from Client # ID
cout << "Position Coords " << x << " : " << y << " : " << z << " " <<PlayerMove.str<<"\n";
This should compile, but I may have made a mistake. I just typed it up on the forum.

Let me know if this works for you and if this makes sense or not as to why I did it this way.
PM me if you need to contact me. Thanks to all the helpful people on this forum especially to Chili.

MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by MrGodin » January 27th, 2015, 3:05 am

Yes it all makes sense but from what i saw, or understood, was sending strings from the struct requires multiple sends if there is more them one string. But hey who am i to say, all i know is it works good :) . But i get it with the way i did, i knew it was a waste of resources but just seemed easier to handle. I suppose there is give and take on all sides of everything eh :)
Curiosity killed the cat, satisfaction brought him back

Pindrought
Posts: 432
Joined: September 26th, 2013, 4:57 pm
Location: Kentucky
Contact:

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by Pindrought » January 27th, 2015, 3:36 am

MrGodin wrote:Yes it all makes sense but from what i saw, or understood, was sending strings from the struct requires multiple sends if there is more them one string. But hey who am i to say, all i know is it works good :) . But i get it with the way i did, i knew it was a waste of resources but just seemed easier to handle. I suppose there is give and take on all sides of everything eh :)
I'm afraid you misunderstood what I was saying. It does not take more than one call to send a struct that has more than one string.

If you want to send a structure that has two floats, and three strings for example, you would do this. Note: You'll need to add TYPE_PacketExampleWithStrings to your Packet Types enum for this test.

Code: Select all

struct PacketExampleWithStrings
{
	int type;
	float float1;
	float float2;
	string str1;
	string str2;
	string str3;
	PacketExampleWithStrings(float myfloat1, float myfloat2, string mystr1, string mystr2, string mystr3)
	{
		type = TYPE_PacketExampleWithStrings;
		float1 = myfloat1;
		float2 = myfloat2;
		str1 = mystr1;
		str2 = mystr2;
		str3 = mystr3;
	}
	PacketExampleWithStrings()
	{
		type = TYPE_PacketExampleWithStrings;
		float1 = 0; float2 = 0;
		str1 = ""; str2 = ""; str3 = "";
	}
};


To send the packet from the client to the server, you would do

Code: Select all

PacketExampleWithStrings PacketToSend(20, 20, "str1", "str2", "str3");
Client->SendDataStructureWithStrings(3, (char*)&PacketToSend, &PacketToSend.str1);
Note: For the int NumberOfStrings argument, we passed 3.

To receive the packet on the server side, you would do

Code: Select all

PacketExampleWithStrings PacketToReceive;
MyPindroughtNetwork->ReceiveAndFillStructureWithStrings(ID, 3, (char*)&PacketToReceive, &PacketToReceive.str1);
Note: For the int NumberOfStrings argument, we passed 3.

I didn't test this code, but this should theoretically work.

Does this make more sense?
PM me if you need to contact me. Thanks to all the helpful people on this forum especially to Chili.

MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by MrGodin » January 27th, 2015, 5:49 am

Yes, thats great. I like the framework for sure. I was just thinking of something though. I may be missing something but ... Now in the ClientThread, there are pointers to the Game. I assume that the thread waits until its chore with the app is done ? .no ?. Now does the app's functions need to be thread safe ?. And say the app is pooping the bed and is slow for some reason performing its task, suspending the thread .. and say the server is still trying to send more data ... does the unreceived packets just get nulled or is there a way to queue them ?.
say push back into a vector, and when going to receive a packet, take the front one ?.
I see a packet loss or something like that if the app is slowing down. I have an app sending data every frame to the server and echo back to the app, works good, but i could see a situation where packet loss could happen
Curiosity killed the cat, satisfaction brought him back

Pindrought
Posts: 432
Joined: September 26th, 2013, 4:57 pm
Location: Kentucky
Contact:

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by Pindrought » January 27th, 2015, 7:02 am

There are no unreceived packets. Since we are using TCP, packets are not lost like in UDP. In a sense the packets are all being queued by the nature of how the thread works.

The recv function is what is receiving the data.

When we are getting the packet type, the thread is stalling at the recv line until it receives the 4 bytes for the type. Once it receives 4 bytes, the recv call is finished. All of the bytes after the recv call are what the framework's built in ReceiveData functions do.

So basically, packets are not lost just because they cannot be instantly processed.

The functions do need to be thread safe, so for certain things you will need to use a queue system, but it is not something that I can easily explain as to when you need to do this or not.

Also, keep in mind that you will always receive the packets in the exact same order that the packets were sent.
PM me if you need to contact me. Thanks to all the helpful people on this forum especially to Chili.

MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by MrGodin » January 27th, 2015, 7:14 am

Awesome man. I'll look more into TCP and UDP documentation .. This is neat stuff, i like it.
Looking forward to your next stuff :)
Curiosity killed the cat, satisfaction brought him back

MrGodin
Posts: 721
Joined: November 30th, 2013, 7:40 pm
Location: Merville, British Columbia Canada

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by MrGodin » January 27th, 2015, 11:00 pm

Hi there. I was looking over some code in the game app, and i noticed you have no handler for dbl clicks and i think i heard something in one of the vids about dbl clicks, i had to do this in the WNDCLASSEX wc when creating the window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;

Was just wondering if you knew that or not.

i haven't tested that in chilli framework
Curiosity killed the cat, satisfaction brought him back

Pindrought
Posts: 432
Joined: September 26th, 2013, 4:57 pm
Location: Kentucky
Contact:

Re: [WIP] Multiplayer Tic Tac Toe Tutorials 10-25-14

Post by Pindrought » January 27th, 2015, 11:21 pm

I didn't say anything about double clicks from what I remember. I haven't experimented with double clicks yet, but that is good to know! :D

Also started working on recording tutorial 4 today.


Got the chat part recorded, just need to do
Add sending X/O packets from client to server and server to client
Add checking if someone won and send message if a player won
Add start new game if a game has ended
Probably going to upload the tutorial in 2 parts because it's already around 30 minutes with just the chat part. Going to try to start uploading part 1 up tonight when I go to sleep. Also found a couple of issues with the solution 4 I had posted originally for the client while recording.
PM me if you need to contact me. Thanks to all the helpful people on this forum especially to Chili.

Post Reply