UDP Client/Server help

Started by
4 comments, last by Garra 12 years, 5 months ago
I'm working on a UDP server/client setup to add to my game. I have the client sending a structure of data representing a packet. This part is working, however I'm having issues trying to get the server to send the packet back out to all the other clients. Basically in my server loop I'm receiving packets, checking to see if the packet is a knock packet, and if it is add that address to a Client address array like below.


while(true)
{
ZeroMemory(szBuffer, sizeof(szBuffer));
//iBytesRecv = c_Network.RecvChatPacket(szBuffer, sizeof(szBuffer)-1, 0);
RecvPacket = c_Network.RecvPacket(RecvPacket);

sprintf(szBuffer, "x: %f y: %f z: %f\n", RecvPacket.x, RecvPacket.y, RecvPacket.z);

//int packet_size = sizeof(RecvPacket);
//
//if (packet_size > 0)
//{
//if the packet is a knock packet
if (RecvPacket.knock)
{
for (int i = 0; i < 8; i++)
{
if (!(c_Network.ClientAddress.sin_family))
{
c_Network.ClientAddress = c_Network.IncomingAddress;
break;
}
}
continue;
}

printf(szBuffer);

c_Network.SendPacketToAll(RecvPacket);

}
.

My client is able to send packets to the server with the below function, so I tried to modify the function to work with my server in order to send the packet to broadcast the packet to the rest of the clients.

void CNetwork::SendPacket(Packet packet)
{
BYTE sendBuffer[128];

memcpy_s(&sendBuffer, 128, &packet, sizeof(packet));

int sent_bytes = 0;
int attempts = 0;
int packet_size = 0;

while (sent_bytes < sizeof(packet) /*&& attempts < 3*/)
{
packet_size = sizeof(packet) - sent_bytes;

int send_err = sendto(skSocket, (char*)&sendBuffer[sent_bytes],
packet_size, 0, (sockaddr*)&ServerAddress, sizeof(sockaddr));

sent_bytes += send_err;
}
}


This function is ment to send the packet from the server to all clients connected. However, the sendto function always returns -1.

void CNetwork::SendPacketToAll(Packet packet)
{
BYTE sendBuffer[128];

memcpy_s(&sendBuffer, 128, &packet, sizeof(packet));

int sent_bytes = 0;
int attempts = 0;
int packet_size = 0;

for (int i = 0; i < 8; i++)
{
if (ClientAddress.sin_family)
{
while (sent_bytes < sizeof(packet))
{
packet_size = sizeof(packet) - sent_bytes;

int send_err = sendto(skSocket, (char*)&sendBuffer[sent_bytes],
packet_size, 0, (sockaddr*)&ClientAddress, sizeof(sockaddr));

if (send_err == SOCKET_ERROR)
{
printf("Unable to send to client\n");
}

sent_bytes += send_err;
//attempts++;
}
}

//Reset variables for use with next client address
sent_bytes = 0;
attempts = 0;
packet_size = 0;
}
}


and here is the server's receive packet function to show how IncomingAddress is being used. When the client starts up it will initialize winsock and then send the knock packet. When the server receives the knock packet it adds the IncomingAddress to the ClientAddress array.

Packet CNetwork::RecvPacket(Packet packet)
{
BYTE recvBuffer[128];
int recvd_bytes = 0;
int packet_size = 0;
int attempts = 0;
int result;

while (recvd_bytes < sizeof(packet))
{
iAddressLength = sizeof(IncomingAddress);
packet_size = sizeof(packet) - recvd_bytes;
result = recvfrom(skSocket, (char*)&recvBuffer[recvd_bytes], packet_size, 0, (sockaddr*)&IncomingAddress, &iAddressLength);

if (result == SOCKET_ERROR)
{

}

recvd_bytes += result;
}

if (recvd_bytes == sizeof(packet))
{
memcpy_s(&packet, sizeof(packet), &recvBuffer, sizeof(packet));
}

return packet;
}
Advertisement

[color=#1C2837][size=2]however I'm having issues trying to get the server to send the packet back out to all the other clients


What are the issues you are having? Compiler errors? Code structure problems? Sending data and never receiving it? Writer's block? :-)
enum Bool { True, False, FileNotFound };
the issue is I'm trying to broadcast the packet received from the client with SendPacketToAll. However inside the SendPacketToAll function I'm calling sendto, which is always returning SOCKET_ERROR and therefore the packet is never broadcasted to the other clients. When I added in breakpoints, it seems like the IncomingAddress isn't being added to the ClientAddress array so I think the problem is here. Could you recommend a different way to handle the client addresses?


for (int i = 0; i < 8; i++)
{
if (!(c_Network.ClientAddress.sin_family))
{
c_Network.ClientAddress = c_Network.IncomingAddress;
break;
}
}


EDIT: I changed my ClientAddress Array to a vector and that seemed to solve most of my issues. It would probably be better to use a list though to make removing clients easier.

if (RecvPacket.knock)
{
c_Network.Clients.push_back(c_Network.IncomingAddress);

}
another quick question, lets say I'm sending packets to update the player positions of a arena type fps. should I be sending the player position's to the server every single game frame?

another quick question, lets say I'm sending packets to update the player positions of a arena type fps. should I be sending the player position's to the server every single game frame?




What happens if you do?
What happens if you don't?
enum Bool { True, False, FileNotFound };
well i haven't actually tried limiting how much I send a packet to update the game, but technically it seems like as long as it updates fast enough then there would be no problem limiting the update to a certain number of frames.

On a different note, I ended up having more issues with broadcasting a client's packet to other clients. When the client and server are on two different machines. The server receives the client's packet without issues and limited packet loss. However, when I try to make the server send that packet to all the other clients, the sendto() function is still returning SOCKET_ERROR and the server message "Unable to send to client" is being displayed. When both client and server are running on the same machine, the server seems to broadcast the packet to the other clients with limited packet loss. However, with the server receiving and broadcasting it is slowing it down greatly. I'm really confused about why the server isn't sending the received packets back out to the clients.

My server's loop

while(true)
{
ZeroMemory(szBuffer, sizeof(szBuffer));
//iBytesRecv = c_Network.RecvChatPacket(szBuffer, sizeof(szBuffer)-1, 0);

RecvPacket = c_Network.RecvPacket(RecvPacket);

if (c_Network.Clients.size() > 0)
{
sprintf(szBuffer, "x: %f y: %f z: %f\n", RecvPacket.x, RecvPacket.y, RecvPacket.z);
}

//if the packet is a knock packet
if (RecvPacket.knock)
{
c_Network.Clients.push_back(c_Network.IncomingAddress);
}
else //if it is a normal packet
{
//broadcast it to all the clients
for (int i = 0; i < c_Network.Clients.size(); i++)
{
c_Network.SendPacketToClient(c_Network.Clients.at(i), RecvPacket);
}
}

printf(szBuffer);
}


SendPacketToClient function

void CNetwork::SendPacketToClient(sockaddr_in client, Packet packet)
{
BYTE sendBuffer[128];

memcpy_s(&sendBuffer, 128, &packet, sizeof(packet));

int sent_bytes = 0;
int attempts = 0;
int packet_size = 0;

while (sent_bytes < sizeof(packet) /*&& attempts < 3*/)
{
packet_size = sizeof(packet) - sent_bytes;

int send_err = sendto(skSocket, (char*)&sendBuffer[sent_bytes],
packet_size, 0, (sockaddr*)&client, sizeof(sockaddr));

if (send_err == SOCKET_ERROR)
{
printf("Unable to send to client\n");
}

sent_bytes += send_err;
}
}

This topic is closed to new replies.

Advertisement