• Advertisement
Sign in to follow this  

sending packet 6300 times every second !

This topic is 2250 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

[size="5"]Old post ---- scroll down to my last post #13

Hello everyone

I'm a network newbie and not long ago i started learning Winsock.

anyways I have a structer that contain player X and Y position and and this structure is being send from the server to the client 6300 times every second. I tried to send it 60 times every second but there was a 1 sec delay from when I pressed Up key to move in the server side till the client respond and moved up.

I had to send the packet 6300 time so there would be no delay. I was just wounding isn't that a bit high. I read that sending packet 200times every second was enough. if that is true then why do I need to send my packet 6300 times ever second for it to not have any delay ?

Server Code:-

#include "Networking.h"
#include "Player.h"

struct PlayerMovment {
int PlayerXPos;
int PlayerYPos;
};

PlayerMovment PlayerPos;
Player P;

Networking::Networking()
{
SendSocket = INVALID_SOCKET;
Port = 27015;
P.SetPosition();
}

Networking::~Networking()
{
}

void Networking::NetworkPlayerPosition(sf::RenderWindow &Window)
{
P.Movment(Window);
PlayerPos.PlayerXPos = P.GetPlayerX();
PlayerPos.PlayerYPos = P.GetPlayerY();
}

void Networking::Init()
{
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
wprintf(L"WSAStartup failed with error: %d\n", iResult);

SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
}
}

void Networking::SendData()
{
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

//wprintf(L"Sending data...");
iResult == sendto(SendSocket, (char*)&PlayerPos, sizeof(PlayerPos), 0, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));

if (iResult == SOCKET_ERROR) {
wprintf(L"sendto failed with error: %d\n", WSAGetLastError());
closesocket(SendSocket);
WSACleanup();
}
}

void Networking::CloseSocket()
{
wprintf(L"Finished sending. Closing socket.\n");
iResult = closesocket(SendSocket);

if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket failed with error: %d\n", WSAGetLastError());
WSACleanup();
}
}

void Networking::CleanUp()
{
wprintf(L"Exiting.\n");
WSACleanup();
}



Main Server Code:-

#include "Networking.h"
#include "Player.h"

int main()
{
Networking N;
Player P;

sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "Network Test with SFML");

N.Init();

P.LoadFile();
P.SetPosition();
sf::Clock Clock;

while (Window.IsOpened())
{
sf::Event Event;
Window.SetFramerateLimit(60);
float ElapsedTime = Window.GetFrameTime();
while (Window.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
Window.Close();
}
N.NetworkPlayerPosition(Window);
int Timer = Clock.GetElapsedTime();

for(int i = 0; i<100; i++)
{
N.SendData(); // sending data 100times * 63FPS = 6300 times every second
}


P.Movment(Window);

Window.Clear();
P.Draw(Window);
Window.Display();
}
N.CloseSocket();
N.CleanUp();
return 0;
}


/----------------------------------------------

Client Code:-

#include "Networking.h"

struct PlayerMovment {
int PlayerXPos;
int PlayerYPos;
};

PlayerMovment PlayerPos;

Networking::Networking()
{
iResult = 0;
Port = 27015;
SenderAddrSize = sizeof (SenderAddr);
}

Networking::~Networking()
{
}

void Networking::Init()
{
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error %d\n", iResult);
}

RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error %d\n", WSAGetLastError());
}
}

void Networking::Bind()
{
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);

iResult = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));

if (iResult != 0) {
wprintf(L"bind failed with error %d\n", WSAGetLastError());
}
}

void Networking::RcevData()
{
//wprintf(L"Receiving datagrams...\n");

iResult = recvfrom(RecvSocket, (char*)&PlayerPos, sizeof(PlayerPos), 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);

if (iResult == SOCKET_ERROR) {
wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
}
}

void Networking::CloseSocket()
{
wprintf(L"Finished receiving. Closing socket.\n");
iResult = closesocket(RecvSocket);

if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
}
}

void Networking::CleanUp()
{
wprintf(L"Exiting.\n");
WSACleanup();
}

int Networking::GetPlayerX()
{
return PlayerPos.PlayerXPos;
}

int Networking::GetPlayerY()
{
return PlayerPos.PlayerYPos;
}


Main Client Code:-

#include "Networking.h"
#include "Player.h"

int main()
{
Networking N;
Player P;

sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "Network Test with SFML");

N.Init();
N.Bind();

P.LoadFile();

while (Window.IsOpened())
{
sf::Event Event;
Window.SetFramerateLimit(60);
while (Window.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
Window.Close();
}

for(int i = 0; i<100; i++)
{
N.RcevData(); // receving data 100times * 63FPS = 6300 times every second
}

P.SetPosition(N.GetPlayerX(), N.GetPlayerY());
Window.Clear();
P.Draw(Window);
Window.Display();
}
N.CloseSocket();
N.CleanUp();
return 0;
}

Share this post


Link to post
Share on other sites
Advertisement

Hello everyone

I'm a network newbie and not long ago i started learning Winsock.

anyways I have a structer that contain player X and Y position and and this structure is being send from the server to the client 6300 times every second. I tried to send it 60 times every second but there was a 1 sec delay from when I pressed Up key to move in the server side till the client respond and moved up.

I had to send the packet 6300 time so there would be no delay. I was just wounding isn't that a bit high. I read that sending packet 200times every second was enough. if that is true then why do I need to send my packet 6300 times ever second for it to not have any delay ?

Server Code:-

#include "Networking.h"
#include "Player.h"

struct PlayerMovment {
int PlayerXPos;
int PlayerYPos;
};

PlayerMovment PlayerPos;
Player P;

Networking::Networking()
{
SendSocket = INVALID_SOCKET;
Port = 27015;
P.SetPosition();
}

Networking::~Networking()
{
}

void Networking::NetworkPlayerPosition(sf::RenderWindow &Window)
{
P.Movment(Window);
PlayerPos.PlayerXPos = P.GetPlayerX();
PlayerPos.PlayerYPos = P.GetPlayerY();
}

void Networking::Init()
{
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR)
wprintf(L"WSAStartup failed with error: %d\n", iResult);

SendSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (SendSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
}
}

void Networking::SendData()
{
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = inet_addr("127.0.0.1");

//wprintf(L"Sending data...");
iResult == sendto(SendSocket, (char*)&PlayerPos, sizeof(PlayerPos), 0, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));

if (iResult == SOCKET_ERROR) {
wprintf(L"sendto failed with error: %d\n", WSAGetLastError());
closesocket(SendSocket);
WSACleanup();
}
}

void Networking::CloseSocket()
{
wprintf(L"Finished sending. Closing socket.\n");
iResult = closesocket(SendSocket);

if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket failed with error: %d\n", WSAGetLastError());
WSACleanup();
}
}

void Networking::CleanUp()
{
wprintf(L"Exiting.\n");
WSACleanup();
}



Main Server Code:-

#include "Networking.h"
#include "Player.h"

int main()
{
Networking N;
Player P;

sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "Network Test with SFML");

N.Init();

P.LoadFile();
P.SetPosition();
sf::Clock Clock;

while (Window.IsOpened())
{
sf::Event Event;
Window.SetFramerateLimit(60);
float ElapsedTime = Window.GetFrameTime();
while (Window.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
Window.Close();
}
N.NetworkPlayerPosition(Window);
int Timer = Clock.GetElapsedTime();

for(int i = 0; i<100; i++)
{
N.SendData(); // sending data 100times * 63FPS = 6300 times every second
}


P.Movment(Window);

Window.Clear();
P.Draw(Window);
Window.Display();
}
N.CloseSocket();
N.CleanUp();
return 0;
}


/----------------------------------------------

Client Code:-

#include "Networking.h"

struct PlayerMovment {
int PlayerXPos;
int PlayerYPos;
};

PlayerMovment PlayerPos;

Networking::Networking()
{
iResult = 0;
Port = 27015;
SenderAddrSize = sizeof (SenderAddr);
}

Networking::~Networking()
{
}

void Networking::Init()
{
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup failed with error %d\n", iResult);
}

RecvSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (RecvSocket == INVALID_SOCKET) {
wprintf(L"socket failed with error %d\n", WSAGetLastError());
}
}

void Networking::Bind()
{
RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(Port);
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY);

iResult = bind(RecvSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr));

if (iResult != 0) {
wprintf(L"bind failed with error %d\n", WSAGetLastError());
}
}

void Networking::RcevData()
{
//wprintf(L"Receiving datagrams...\n");

iResult = recvfrom(RecvSocket, (char*)&PlayerPos, sizeof(PlayerPos), 0, (SOCKADDR *) & SenderAddr, &SenderAddrSize);

if (iResult == SOCKET_ERROR) {
wprintf(L"recvfrom failed with error %d\n", WSAGetLastError());
}
}

void Networking::CloseSocket()
{
wprintf(L"Finished receiving. Closing socket.\n");
iResult = closesocket(RecvSocket);

if (iResult == SOCKET_ERROR) {
wprintf(L"closesocket failed with error %d\n", WSAGetLastError());
}
}

void Networking::CleanUp()
{
wprintf(L"Exiting.\n");
WSACleanup();
}

int Networking::GetPlayerX()
{
return PlayerPos.PlayerXPos;
}

int Networking::GetPlayerY()
{
return PlayerPos.PlayerYPos;
}


Main Client Code:-

#include "Networking.h"
#include "Player.h"

int main()
{
Networking N;
Player P;

sf::RenderWindow Window(sf::VideoMode(800, 600, 32), "Network Test with SFML");

N.Init();
N.Bind();

P.LoadFile();

while (Window.IsOpened())
{
sf::Event Event;
Window.SetFramerateLimit(60);
while (Window.GetEvent(Event))
{
if (Event.Type == sf::Event::Closed)
Window.Close();
}

for(int i = 0; i<100; i++)
{
N.RcevData(); // receving data 100times * 63FPS = 6300 times every second
}

P.SetPosition(N.GetPlayerX(), N.GetPlayerY());
Window.Clear();
P.Draw(Window);
Window.Display();
}
N.CloseSocket();
N.CleanUp();
return 0;
}



Don't recieve data a fixed number of times per frame, recieve all packets that are pending each frame instead (on both client and server), otherwise you run the risk of flooding the buffer if the framerate drops and send the data once per frame on both aswell, (Sending the same data 100 times per frame is pointless).

To hide the latency you should allow the client to move as soon as it presses the button, other players will lag behind slightly but if you stop flooding the buffers it will only be a few milliseconds.

Share this post


Link to post
Share on other sites
thank you for the replay.

as i said i'm a network newbie :D and i just have few more questions.


recieve all packets that are pending each frame instead (on both client and server),


how do i do that exacly ?


otherwise you run the risk of flooding the buffer if the framerate drops and send the data once per frame on both aswell

i didn't understand you. Can you please explain it more.


To hide the latency you should allow the client to move as soon as it presses the button

how do i do that too ?

sorry i know that I'm asking way too much but i really don't know that much about network programing.
thank you

Share this post


Link to post
Share on other sites
It seems that you are truly sending the same data 100 times per iteration and receiving the same data 100 times per iteration and finally you set the position just once per iteration. This doesn't make sense.

Probably your networking API waits a certain buffer to get full before sending it. It may have something to do with so called "Nagle's algorithm" which you should disable.
So practically you aren't sending 6000 packets per second.

There is always more or less of latency when transmitting data and that's one thing to over come.

Cheers!

Share this post


Link to post
Share on other sites

thank you for the replay.

as i said i'm a network newbie :D and i just have few more questions.

[quote name='SimonForsman' timestamp='1323780719' post='4893474']
recieve all packets that are pending each frame instead (on both client and server),


how do i do that exacly ?
[/quote]

You are sending the exact same data 100 times each frame here:



while (Window.IsOpened())
{

...

for(int i = 0; i<100; i++)
{
N.SendData(); // sending data 100times * 63FPS = 6300 times every second
}

...



The same goes for receiving. Remove the for-loop around it, and you'll send your data once each frame.


Also, I would suggest that you calculate the speed of the moving object on the client. Add this speed to your old character position and you have the new position. (You could calculate that by measuring the distance between two position updates divided by the time needed to travel that distance). Don't forget to compare the interpolated position with the actual position from time to time to make sure it is still correct.

That way the character of a player moves more fluent on the screen of another player even with a rather low rate of received network updates.




EDIT: ARGH kauna was faster ;)


Share this post


Link to post
Share on other sites
You don't need to send so much that, that is overkill, you can just interpolate/extrapolate values.
Check this:
www.mindcontrol.org/~hplus/epic/

Share this post


Link to post
Share on other sites

thank you for the replay.

as i said i'm a network newbie :D and i just have few more questions.

[quote name='SimonForsman' timestamp='1323780719' post='4893474']
recieve all packets that are pending each frame instead (on both client and server),


how do i do that exacly ?
[/quote]
http://msdn.microsof...v=vs.85%29.aspx


otherwise you run the risk of flooding the buffer if the framerate drops and send the data once per frame on both aswell

i didn't understand you. Can you please explain it more.
[/quote]
Right now you're sending a fixed number of packets per iteration on the server and reading a fixed number of packets per iteration on the client, if the framerate on the client drops even a tiny bit below that of the server you will send data faster than you are recieving it and the clients buffers will get full.


To hide the latency you should allow the client to move as soon as it presses the button

how do i do that too ?

sorry i know that I'm asking way too much but i really don't know that much about network programing.
thank you
[/quote]
You do that in exactly the same way as you would for a singleplayer game.

Share this post


Link to post
Share on other sites

anyways I have a structer that contain player X and Y position and and this structure is being send from the server to the client 6300 times every second. I tried to send it 60 times every second but there was a 1 sec delay from when I pressed Up key to move in the server side till the client respond and moved up.


60 times per second is probably too much -- a successful FPS game like HALO only sends packets 15 times a second. But 60 times a second is doable. 6300 is not.

The problem you're running into is quite likely related to TCP_NODELAY, and is described in the FAQ for this forum. Once you set that option on your socket, you should be fine wiht 60 times a second. Or 20.

Share this post


Link to post
Share on other sites
Many games can get away with rates as low as 10 times per second with relatively high latency -- which is about right for the average connection speed in the US as a worst-case-scenario. I recall reading somewhere that this is even a requirement for Xbox Live certification -- that a game has to be relatively playable at 10 packets/s with 200ms latency or somesuch. You'll likely experience greater rates than that in practice online, and greater still in a LAN environment, but you want to work at those rates, even if it means gracefully degrading the quality of the client-side experience for that player.

Google "dead reckoning" to read about how to reduce apparent client-side latency.

Share this post


Link to post
Share on other sites

[quote name='FantasyVI' timestamp='1323779847' post='4893473']
anyways I have a structer that contain player X and Y position and and this structure is being send from the server to the client 6300 times every second. I tried to send it 60 times every second but there was a 1 sec delay from when I pressed Up key to move in the server side till the client respond and moved up.


60 times per second is probably too much -- a successful FPS game like HALO only sends packets 15 times a second. But 60 times a second is doable. 6300 is not.

The problem you're running into is quite likely related to TCP_NODELAY, and is described in the FAQ for this forum. Once you set that option on your socket, you should be fine wiht 60 times a second. Or 20.
[/quote]

It can't be a Nagle issue since he's using UDP. That should be sending the packet every time he calls sendto.

OP, you really should just send movement data once, and, when receiving data, make a call to select to check if there's data on the socket. if so, read it out and process it.

Share this post


Link to post
Share on other sites
It looks like everyone has forgotten the most important thing, remember to set the UDP sockets as non-blocking. Otherwise each frame you'll be waiting for a packet to arrive, which is no good.Then just send one packet per frame.Do not expect to receive one packet every frame. This is important otherwise your client is going to gradually lag further and futher behind the server. Instead receive as many packets as you can. Loop until the receive indicates there are no more packets, it either returns a zero length or a would block error. Off hand I don't remember which. This way if one packet gets lost or one packet is delivered at nearly the same time as the next then you will exhaust all packets received during the frame.

Share this post


Link to post
Share on other sites

It can't be a Nagle issue since he's using UDP. That should be sending the packet every time he calls sendto.


Totally true! I was only going by the symptoms, I didn't scroll down the code.

So, with UDP, your problem is more likely either
1) not properly using select() and/or non-blocking sockets for receiving -- make sure to use proper polling
2) not properly draining the receive socket each iteration (you may get 0, 1, or many packets) -- make sure you read until it's dry
3) CPU scheduling -- the sender sends, but never releases the CPU for the receiver. Try adding a Sleep(10) at the top of the outer while() loop

Share this post


Link to post
Share on other sites
first of all thank you guys for the replays and sorry its been a while because i had some college work to do.
can you please tell me how to use select() ? i tried research it and i read Beej's Guide to Network Programming but i didn't understand how to use select(). all i understand is select() is good for server that has more than one client and receive from more than one socket but i can't understand the source code or how to use it.

i have discovered that sometimes when i run my server and client and press any key to move the player sometimes the client lag behind and sometimes when i close the server and client and open them again the client doesn't lag behind.

BTW i removed the two for() loops in my code. now the server is sending 60 packet per sec and the client is receiving 60 packet ever sec, i guess.

one more question, how can I make my server accept multiple clients and update all of their data?


It looks like everyone has forgotten the most important thing, remember to set the UDP sockets as non-blocking. Otherwise each frame you'll be waiting for a packet to arrive, which is no good.Then just send one packet per frame.Do not expect to receive one packet every frame. This is important otherwise your client is going to gradually lag further and futher behind the server. Instead receive as many packets as you can. Loop until the receive indicates there are no more packets, it either returns a zero length or a would block error. Off hand I don't remember which. This way if one packet gets lost or one packet is delivered at nearly the same time as the next then you will exhaust all packets received during the frame.

I assume that I have to use select() to check if the server started to send data.


[quote name='BeerNutts' timestamp='1324174758' post='4894921']
It can't be a Nagle issue since he's using UDP. That should be sending the packet every time he calls sendto.


Totally true! I was only going by the symptoms, I didn't scroll down the code.

So, with UDP, your problem is more likely either
1) not properly using select() and/or non-blocking sockets for receiving -- make sure to use proper polling
2) not properly draining the receive socket each iteration (you may get 0, 1, or many packets) -- make sure you read until it's dry
3) CPU scheduling -- the sender sends, but never releases the CPU for the receiver. Try adding a Sleep(10) at the top of the outer while() loop
[/quote]

I'm sure its not 3 but how do i use 1 and 2.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement