Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Simple TCP connect between 2 PC's doesn't work  (Read 10401 times)

0 Members and 3 Guests are viewing this topic.

ingwik

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Simple TCP connect between 2 PC's doesn't work
« on: March 18, 2012, 10:02:57 pm »
Environment: Win 7 Enterprise 64, VC++ 2010 express, SFML 1.6

I'm trying to make a simple game. A boy is running from a cow. The boy is running on the server PC and the cow is running on the client. It's a simple test to see if it's possible to run a two player game over a LAN. I've followed the tutorials but somehow, I'm stuck.

The class both inherit from (could as well has been a struct, I think):
Code: [Select]
class spelare
 {
 public:
  sf::Uint8   ID; //0=boy, 1=cow
  sf::Int32 hastighetX; //velocity, x
  sf::Int32 hastighetY; //velocity y
  sf::Sprite sprite; //Sprite with pic
 };


The packet, more or less a copy from the lesson:
Code: [Select]
sf::Packet &operator <<(sf::Packet &Packet, const spelare &C)
 {return Packet << C.ID << C.hastighetX << C.hastighetY;}

 sf::Packet &operator >>(sf::Packet &Packet, spelare &C)
 { return Packet >> C.ID >> C.hastighetX >> C.hastighetY;}


Function for a server, this function seems to work just fine.
 
Code: [Select]
void RunServer(unsigned short Port)
 {
    sf::SocketTCP Server;

    if (!Server.Listen(Port))
        return;
    std::cout << "Listen on port " << Port << ", wait for connect... " << std::endl;

    sf::IPAddress ClientAddress;
    sf::SocketTCP Client;
    Server.Accept(Client, &ClientAddress);
    std::cout << "Client connected : " << ClientAddress << std::endl;
 }


And the client, seems to work too.
Code: [Select]
void RunClient(unsigned short Port)
{
    sf::IPAddress ServerAddress;
    do
    {
        std::cout << "IP to connect to? : ";
        std::cin  >> ServerAddress;
    }
    while (!ServerAddress.IsValid());
    sf::SocketTCP Client;

    if (Client.Connect(Port, ServerAddress) != sf::Socket::Done)
        return;
    std::cout << "Connected to server " << ServerAddress << std::endl;
 }


These two functions are run once, at the startup before any windows are shown. I suppose they will be valid for the rest of the session.

Then, I have a function to send the packet with information. Since I never recieve anything, I'm not really sure if it works, but I think something is sent...

Code: [Select]
 void PlayerSend(class spelare &s)
{
    spelare C = {s.ID, s.hastighetX, s.hastighetY};
    sf::Packet RegularPacket; //Packet created
    sf::SocketTCP Client; //Socket created
    RegularPacket << C; //Packet recieve it's three values

   if (C.ID == 0)
  {std::cout << "Boy sent to client: " << std::endl;}
  else
  {std::cout << "Cow sent to client: " << std::endl;}

    if (Client.Send(RegularPacket) != sf::Socket::Done)
        return;
}


And finally, the recieving function that doesn't seem to work at all.

Code: [Select]
void PlayerRecieve(class spelare &s)
  {
  sf::Packet RegularPacket; //Packet created
  sf::SocketTCP Client;
 //Client.SetBlocking(false);
  spelare C; //Create new C
 
      if (Client.Receive(RegularPacket) != sf::Socket::Done)
   return;
 //Nothing below this point ever activates

    if (RegularPacket >> C)
    {
        if (C.ID == 0)
    {std::cout << "Boy recieved from server: " << std::endl;}
   else
    {std::cout << "Cow recieved from server: " << std::endl;}

    }
   else //No regular packet C recieved
    {std::cout << "Nothing recieved from server: " << std::endl;}
  }


The "PlayerSend" function fires every time an arrow key is pressed so it should be possible for the other PC to have the player moved.

The "PlayerRecieve" function is fired just before the cow and boy are moved. As it is now, it's possible for the client to move the cow and the server to move the boy and it seems as if the two computers are connected somehow.

I can't find what I'm doing wrong. I have followed the tutorial but obviously I have made something wrong. If someone else who is better than I can show me what might be wrong, I'll apprciate it a lot.

Yours sincerely

Ingemar

(The complete code, even though the comments are in swedish, can be found here at the bottom of the page)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Simple TCP connect between 2 PC's doesn't work
« Reply #1 on: March 19, 2012, 07:56:26 am »
You're creating a new socket in your PlayerSend (and PlayerRecieve) function, instead of using the one that you previously connected. It can't work ;)
Laurent Gomila - SFML developer

ingwik

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Simple TCP connect between 2 PC's doesn't work
« Reply #2 on: March 19, 2012, 08:20:09 am »
So, what I have to do is to create a socket outside the functions in main or as a global and then use the same socket within all functions?

Or, am I supposed to make two different sockets? One to send and one to recieve? i.e.:

sf::SocketTCP Server;
and
sf::SocketTCP Client;


Thanks Laurent, for your quick answer.

//Ingemar

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Simple TCP connect between 2 PC's doesn't work
« Reply #3 on: March 19, 2012, 08:42:47 am »
Quote
So, what I have to do is to create a socket outside the functions in main or as a global and then use the same socket within all functions?

Yes.

Quote
Or, am I supposed to make two different sockets? One to send and one to recieve?

No.
Laurent Gomila - SFML developer

ingwik

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Simple TCP connect between 2 PC's doesn't work
« Reply #4 on: March 19, 2012, 10:52:55 am »
I changed the code to use just one TCP socket. But I am not sure if I’m supposed to use one packet that move back and forth, or use one packet to send and one other packet to receive.

Now, I have these as globals:

Code: [Select]
//Create one global packet
 sf::Packet RegularPacket; //Id, x and y velocity

 // Create one global TCP socket
 sf::SocketTCP spelsocket;


The send function looks like this now:

 
Code: [Select]
void PlayerSend(class spelare &s)
{
spelare C = {s.ID, s.hastighetX, s.hastighetY};
RegularPacket << C;

if (C.ID == 0)
{std::cout << "Boy sent to client: " << std::endl;}
else if (C.ID == 1)
{std::cout << "Cow sent to client: " << std::endl;}
else
{std::cout << "Garbage sent to client: " << std::endl;}

if (spelsocket.Send(RegularPacket) != sf::Socket::Done)
        return;
}



And the receive function looks like this:

 
Code: [Select]
void PlayerRecieve(class spelare &s)

  {
spelsocket.SetBlocking(false); //Prevents connection otherwise
spelare C;

if (RegularPacket >> C)
   {
    if (C.ID == 0)
    {std::cout << "Boy received from server: " << std::endl;}
    else if(C.ID == 1)
   {std::cout << " Cow received from server: " << std::endl;}
 else
{std::cout << "Garbage received from server: " << std::endl;}

//Let the player sprite claim the values from the sent class/struct
s.hastighetX = C.hastighetX;
s.hastighetY = C.hastighetY;

// RegularPacket.Clear();
    }
else
{std::cout << " Nothing received from server: " << std::endl;}

if (spelsocket.Receive(RegularPacket) != sf::Socket::Done)
return;

  }



My problem now is that the boy is sending and also receiving himself (and so is the cow). It means that the cow and the boy sprites move in the same pattern for each player but the computers have no contact with each other, or at least so it seems.

I’ve tried to clear the packet with “// RegularPacket.Clear(); “ after the values have been given to the sprite/class, assuming that the reason for the unchanged ID value is that the same package is sent back and forth. But I’m really not sure about why it doesn’t seem to change ID when it obviously change X and Y values.’

Any input to the problem would be highly appreciated.

//Ingemar

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Simple TCP connect between 2 PC's doesn't work
« Reply #5 on: March 19, 2012, 10:55:42 am »
Don't reuse packets, especially between send and receive, and especially with non-blocking sockets! Just create one whenever you need to (right before sending / receiving).
Laurent Gomila - SFML developer

ingwik

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Simple TCP connect between 2 PC's doesn't work
« Reply #6 on: March 19, 2012, 12:40:03 pm »
Quote from: "Laurent"
Don't reuse packets, especially between send and receive, and especially with non-blocking sockets! Just create one whenever you need to (right before sending / receiving).


New try, I removed the global packet and creates a packet inside the function instead.

Code: [Select]
void PlayerSend(class spelare &s)
{
sf::Packet ToSend;
 ToSend << s.ID << s.hastighetX << s.hastighetY;

 if (spelsocket.Send(ToSend) != sf::Socket::Done)
        return;
}


And the recieving end:

Code: [Select]
void PlayerRecieve(class spelare &s)
  {
 spelsocket.SetBlocking(false);
 spelare R;
 sf::Packet Received;

 if (Received >> R)
    {
        if (R.ID == 0)
       {std::cout << "Boy recieved from server: " << std::endl;}
       else if(R.ID == 1)
      {std::cout << "Cow recieved from server: " << std::endl;}
      else
     {std::cout << "Garbage recieved from server: " << std::endl;}
    }
  else
    {std::cout << "Nothing recieved from server: " << std::endl;}
      s.hastighetX = R.hastighetX;
      s.hastighetY = R.hastighetY;

   if (spelsocket.Receive(Received) != sf::Socket::Done)
 return;
  }

I'm constantly getting "Nothing recieved from server: " even when I try to run both a server and a client on my own, single machine. Any idea?

//Ingemar

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Simple TCP connect between 2 PC's doesn't work
« Reply #7 on: March 19, 2012, 01:14:17 pm »
Quote
I'm constantly getting "Nothing recieved from server: "

Yeah, since you extract data from the packet before receiving it ;)
Laurent Gomila - SFML developer

ingwik

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Simple TCP connect between 2 PC's doesn't work
« Reply #8 on: March 19, 2012, 02:30:06 pm »
Obviously, you see something that I don't Laurent:

*I create a player dummy
*I create a packet
*I check if I recieve something
*If I recieve something I get a message
*If I don't recieve anything, I get another message
*I Give the player the values from the dummy struct
*I keep doing it as long as the information keep coming

Where do I extract before recieving?

if I put this at the very beginning in the recieve function. The program ends before any messages and the screen freeze after connect and window creation but before any graphic is shown:
Code: [Select]
sf::Packet Received;
 if (spelsocket.Receive(Received) != sf::Socket::Done)
 return;


//Ingemar

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Simple TCP connect between 2 PC's doesn't work
« Reply #9 on: March 19, 2012, 02:34:14 pm »
Code: [Select]
sf::Packet Received; // <----- you create the packet

if (Received >> R) <----- you extract data
...

if (spelsocket.Receive(Received) != sf::Socket::Done) <----- you receive
Laurent Gomila - SFML developer

ingwik

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Simple TCP connect between 2 PC's doesn't work
« Reply #10 on: March 19, 2012, 02:44:09 pm »
Something is odd, even if I shrink the code for recieving to:
Code: [Select]
 void PlayerRecieve(class spelare &s)
  {
 sf::Packet Received;
 if (spelsocket.Receive(Received) != sf::Socket::Done)
 return;
 spelsocket.SetBlocking(false);
}


The program freeze, turns white and nothing else happens. It doesn't matter if I set blocking to true or false. Odd, really odd, and I have no clue about how to fix it.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Simple TCP connect between 2 PC's doesn't work
« Reply #11 on: March 19, 2012, 02:47:16 pm »
You set the socket as non-blocking after trying to receive data...

Seriously, do you understand at least a little bit what you're writting?
Laurent Gomila - SFML developer

ingwik

  • Jr. Member
  • **
  • Posts: 65
    • View Profile
Simple TCP connect between 2 PC's doesn't work
« Reply #12 on: March 19, 2012, 02:54:15 pm »
I am seriously trying to understand. I really do appreciate the help you are giving me Laurent. My biggest problem is that all other sides of C++ programming and game programming are covered one way or the other in hundreds of e-books out on the Internet, but network programming is hardly mentioned anywhere. That puts me in an awkward situation where I try to learn from the few sources that are around, and try to implement that slim knowledge to SFML that has a standard of its own. I do my best, have patience with me please.

And yes, after sitting in front of a PC and being programming a long time with few breaks, you do silly mistakes. Putting blocking to false before recieving the packet made the game run as it should again.

One thing that I don't understand though is why no code at all is executed after
Code: [Select]
if (spelsocket.Receive(Received) != sf::Socket::Done)
 return;

The code breaks and not a single line of code or any couts of any kind is sent to the screen. If you, or any one else can give a hint, I think I can have a chance to make it run as it should .

I'm a "doer" when coming to programming. If I get a piece of code that works, I can build on that and continue to make more and more advanced routines. The problem is that I need to see just one working example, that's what I'm working with, and asking for, here.

//Ingemar

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Simple TCP connect between 2 PC's doesn't work
« Reply #13 on: March 19, 2012, 03:10:58 pm »
I'm glad you made it work.

This is exactly what I meant: sometimes you need to take a break, think quietly about what you've done, what could be wrong, the logic of the program, etc. Instead of rushing to the forum after every error :)

I know it's hard to begin, especially with network. It's hard to find "generic" tutorials that explain the basic concepts.
Laurent Gomila - SFML developer

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Simple TCP connect between 2 PC's doesn't work
« Reply #14 on: March 19, 2012, 03:13:29 pm »
Quote
One thing that I don't understand though is why no code at all is executed after
Code: [Select]
if (spelsocket.Receive(Received) != sf::Socket::Done)
 return;

If the socket is in blocking mode, this function will wait for data before returning. That's what "blocking" means, it blocks the execution.

This is explained in the doc/tutorials, isn't it? ;)
Laurent Gomila - SFML developer