Reputation: 117
Currently I am in the midst of trying to create a UDP peer-to-peer network program. I have a UDP class which encapsulates the data and functions necessary to set up the socket and port for a single connection to another client on the network and functions allowing the program to send and receive data packets across the network. The trouble is although second client application receives the data packet from the first client and updates its output accordingly, the first client does not receive the packet update sent from the second client. This is despite the fact that the networking code governing both applications is effectively the same. – I have called the bind() function for each application (which will eventually be run on different machines) as I read it is better if the machine is having to listen for incoming connections. Also there is an fd_set in both applications which should ensure that the program does not block on the recvfrom function and should continue if no message is received (but this is only ever the case when the applications are starting up). My question is: why is the recvfrom function halting the program execution in the UDP class?
Here is the code for the client:
#ifndef _UDPCLASS_H_
#define _UDPCLASS_H_
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <winsock2.h>
#include "Player.h"
using namespace std;
//Client port and IP
#define SERVERIP "127.0.0.1"
#define LISTENINGPORT 4444
class UDPClass
{
public:
//Functions
UDPClass(); //Constructor
~UDPClass(); //Destructor
struct Message
{
int objectID; //the ID number of the object
int x, y; //position
};
//Variables
SOCKET sock;
char message[MESSAGESIZE]; //Array of chars to store messages
sockaddr_in toAddr; //The address of the client socket
//Function Prototypes
//Functions related to sending packets to other players
void Initialise(); //Set up client socket
void sendMessage(); //Send data from player via message struct to server
//RECIEVING
//Functions related to recieving packets from other players
void recieveMessage();
void checkID(Message* mess);
//Variables
Message* playerStats; //Variable to hold the player's coordinates and ID
Message* player2Stats; //Variable to store player 2's statitstics such as position data in a message recieved from the server
PlayerClass* PlayerU; //Instance of class player to transfer data into message
PlayerClass* PlayerO; //Instance of player class to represent otehr player
private:
};
#endif
UDPClass .cpp file:
#include "UDPClass.h"
UDPClass::UDPClass()
{
//Initialises the socket to be a UDP socket
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == INVALID_SOCKET) {
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
}
PlayerU = NULL;
PlayerO = NULL;
}
UDPClass::~UDPClass()
{
closesocket(sock);
WSACleanup();
}
void UDPClass::Initialise()
{
// Fill out a sockaddr_in structure with the address that
// we want to send to.
toAddr.sin_family = AF_INET;
// htons converts the port number to network byte order (big-endian).
toAddr.sin_port = htons(LISTENINGPORT);
toAddr.sin_addr.s_addr = inet_addr(SERVERIP);
//Bind the socket to the address of this address.
if (bind(sock, (LPSOCKADDR) &toAddr, sizeof(toAddr)) != 0)
{
printf("bind failed");
}
//Initialise an instance of type player class for the player of THIS client
PlayerU = new PlayerClass;
//NEW - in version 7.2 initialise an instance of the player class to store the data recieved in messages from other machines
PlayerO = new PlayerClass;
//Now we initialise a struct of type Message to contain data that we wish the other client to recieve
playerStats = new Message;
playerStats->objectID = PlayerU->getID();
//Put the players current position into Message struct containing data that will be sent to the server
playerStats->x = PlayerU->getX();
playerStats->y = PlayerU->getY();
printf("Control the player using the directional arrow keys ");
}
void UDPClass::sendMessage()
{
fflush(stdout);
playerStats->x = PlayerU->getX();
playerStats->y = PlayerU->getY();
int count = sendto(sock,
(char*) playerStats, sizeof(Message), 0, (SOCKADDR *)& toAddr, sizeof (toAddr));
if(count == SOCKET_ERROR)
{
printf("ERROR: %d \n", WSAGetLastError());
}
}
void UDPClass::recieveMessage()
{
//Variables describing the struct that defines the sockets the client is interested in listening to
fd_set readable;
FD_ZERO(&readable);
FD_SET(sock, &readable);
// The structure that describes how long to wait for something to happen.
timeval timeout;
// We want a 2.5-second timeout.
timeout.tv_sec = 2;
timeout.tv_usec = 500000;
fflush(stdin);
player2Stats = new Message;
// Read a response back from the server (or from anyone, in fact).
sockaddr_in fromAddr;
int fromAddrSize = sizeof(fromAddr);
int count = recvfrom(sock, (char*)player2Stats, sizeof(Message), 0,
(sockaddr *) &fromAddr, &fromAddrSize);
//Call checkID to give player two representation latest updates
checkID(player2Stats);
}
void UDPClass::checkID(Message* mess)
{
//Set the player stats of the other player this player is playing with to the values of the incoming message
PlayerO->SetID(mess->objectID);
PlayerO->SetX(mess->x);
PlayerO->SetY(mess->y);
}
In the main application there is a continuous while loop which executes the network functions like so:
//Declare instance of a client to send and recieve messages
UDPClass client1;
//Initialise clients
client1.Initialise();
while(TRUE)
{
//Update the 2nd player position
client1.recieveMessage();
updateOther(client1);
client1.checkPlayPos(Player.x, Player.y);
client1.sendMessage();
}
With the updateOther function definition looking something like this:
void updateOther(UDPClass &theClient)
{
//Update the position of the 2nd player on screen by making the coordinates equal to data recieved from incoming message
Player2.x = theClient.PlayerO->getX();
Player2.y = theClient.PlayerO->getY();
}
In the main while loop if the two lines of code relating to the recieving of messages are commented out like so:
/*client1.recieveMessage();
updateOther(client1);*/
The program runs fine but if they are executed the program freezes so I am obviously doing something wrong with the recvfrom function - I was wondering if it was blocking?
Upvotes: 0
Views: 1716