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

Author Topic: How to create a UDP "chat"  (Read 5960 times)

0 Members and 1 Guest are viewing this topic.

Cosmin_NTG

  • Newbie
  • *
  • Posts: 2
    • View Profile
How to create a UDP "chat"
« on: December 27, 2012, 09:30:07 pm »
Hello!

I try to create a...kind of chat using a UDP socket.

I started with the examples in the tutorial about UDP sockets and I modified them a bit.

I want to create two separate programs (the server and the client) and to communicate each other. Until now, only the client can send messages to the server.

Here is the code for the server application:

#include<SFML/Network.hpp>
#include<iostream>
#include<cstring>

void DoServerUDP(unsigned short Port)
{
    // Create a UDP socket for communicating with clients
    sf::SocketUDP Server;

    // Bind it to the specified port
    if (!Server.Bind(Port))
        return;

    // Receive a message from anyone
    sf::IPAddress ClientAddress = sf::IPAddress::LocalHost;
    unsigned short ClientPort;
    char Message[128];
    char SendingMessage[200];
    std::size_t Received;

    int i=0;
    while(i<100)
    {

          Server.Receive(Message, sizeof(Message), Received, ClientAddress, ClientPort);
          std::cout <<"Client: "<< Message << "\n" << std::endl;
       /*   std::cin.getline(SendingMessage, 200);
          Server.Send(SendingMessage,sizeof(SendingMessage), ClientAddress, ClientPort);*/


        i++;
    }

    // Close the socket when we're done
    Server.Close();
}
int main()
{
    const int port = 2343;
    std::cout<<"Hello! The UDP server has been started. Now, the server waits for messages.";
    std::cout<<"\n";
    DoServerUDP(port);
    std::cout<<"Press enter to exit...";
    std::cin.ignore(10000, '\n');
    std::cin.ignore(10000, '\n');
    return EXIT_SUCCESS;
}
 

And this is the code for the client application:

#include<SFML/Network.hpp>
#include<iostream>
#include<cstring>

void DoClientUDP(unsigned short Port)
{
    // Ask for server address
    sf::IPAddress ServerAddress;
    do
    {
        std::cout << "Type address or name of the server to send the message to : ";
        std::cin  >> ServerAddress;
    }
    while (!ServerAddress.IsValid());
    char Message[3000];
    // Create a UDP socket for communicating with server
    sf::SocketUDP Client;

    std::cout<<"You will now start the conversation with server: ";
    std::cin.getline(Message, 3000);
    std::size_t Received;
    char MessageReceived[256];

    int i=0;
    while(i<100)
    {


       Client.Send(Message, sizeof(Message), ServerAddress, Port);

       std::cin.getline(Message, 3000);

      i++;

    }
    // Close the socket when we're done
    Client.Close();
}

int main()
{
    const int port = 2343;
    std::cout<<"Welcome to the Client application!";
    std::cout<<"\n";
    DoClientUDP(port);
    std::cin.ignore(10000, '\n');
    std::cin.ignore(10000, '\n');
    return EXIT_SUCCESS;

}
 

As a server address, I use my local host: 127.0.0.1

How can I modify them so that the server can send messages to the client?

Thank you respectfuly.

P.S. Please excuse my english, I'm not a native speaker.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10846
    • View Profile
    • development blog
    • Email
Re: How to create a UDP "chat"
« Reply #1 on: December 27, 2012, 09:43:14 pm »
Well we're not here to write you some finished code... ;)
But since we like to help, you should also state what you've already achieved and where you're stuck.
There's an existing tiny chat on the official SFML wiki, but it uses TCP sockets and the whole networking topic is quite big, so you'll most probably find some general topics about it.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Nephatrine

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: How to create a UDP "chat"
« Reply #2 on: December 28, 2012, 12:15:04 am »
What is your use case for wanting a chat program based off UDP? Just to experiment? Chat programs are usually more well-suited to TCP since reliability is pretty paramount to chat. I just finished a TCP chat lobby program using SFML2/SFGUI and it really wasn't too hard and wouldn't be difficult to port over to UDP. You are going to need to be either polling non-blocking sockets or doing your listening on threads, however, as otherwise you'll be stuck listening for new packets and never be able to do anything else.

As for the issue, you are having, can you clarify what you need done? Are you wanting the server to act as a client itself and chat from it or are you just wanting it to be able to forward the messages it receives to other client(s)? Is it going to just be the one server and one client... or were you going to allow for multiple clients at some point?
« Last Edit: December 28, 2012, 12:31:32 am by Nephatrine »

Cosmin_NTG

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: How to create a UDP "chat"
« Reply #3 on: December 28, 2012, 11:47:41 am »
I nerver said that I want a finished code.

I chose UDP because I thought it was a bit simpler than TCP. I am a newbie in network programming, so I want to learn the basics first (using that example).

So yes, I am doing that program because I just want to experiment.

On the other hand, I want to make a simple communication between the server and the client.
More exactly: the server and the client must have the sending and receiving properties so that the server can receive messages from the client and to send messages too, as same as the client. 


I am stuck in the following situation: the server must receive messages (as it does in the code below) but it also has to send messages. Now, I don't know how to make a kind of algorithm which knows when to send the messages at the appropriate time (if I type something in the server - application and I hit enter, the client should see my message in his application; but what if the client is typing in the same time I hit enter? does he receive my message?);  the same situation is in the client - application. In some way, both applications must wait for the message or...someting like that.

I've seen that chat - application made using TCP sockets but it was a bit hard to understand for me because I  don't know many things about threads and mutex or whatever.

I want something as simple as possible.

Thank you respectfully.

Nephatrine

  • Newbie
  • *
  • Posts: 2
    • View Profile
Re: How to create a UDP "chat"
« Reply #4 on: December 28, 2012, 10:12:51 pm »
UDP is not "reliable" which means packets may be dropped and aren't guaranteed to reach the destination in order or even at all. That makes it a poor choice for chat unless you want to do a lot of additional coding to tack on that functionality. Really the only way that it's simpler is that it is connection-less and your server would just need the one socket to talk to all the clients rather than having to use a SocketSelector. If you just want the one client, however, you can do without a SocketSelector and just have a Listener to accept connections and another Socket for the client once it connects. Look at the chat example eXpl0it3r linked to see how to do almost exactly what you're currently doing with TCP.

To have the client and server both receive and send messages, you'll either need to use non-blocking sockets (though you won't want to use std::cin since it blocks) or use multiple threads. I prefer using threads.

SERVER
- Wait for connection on listener.

CLIENT
- Connect to server.

BOTH
- Once you have a connection, spawn a thread listening on client socket for messages to display.
- In main loop, handle user input and send messages out.

If the client disconnects, the server will need to go back to waiting for connections. This is not an ideal setup but is very simple. Since you're doing everything from the console with std::cin and std::cout, however, you'll probably end up with interleaved output and input in the console due to the threading. For instance, if you're halfway through typing something to send and a message is received, you'll really confuse things if you just write it to the console.

In a better client-server architecture, you'd want the server to just listen and forward messages to other clients (aside from the original sender). This server wouldn't take any user input and would just be background process. You could then just spawn two clients and test by talking to eachother. You'd need to use a SocketSelector on the server to listen for both incoming connections on the Listener and to all the connected client Sockets at the same time. You'd also want to come up with some way to uniquely identify each connected user so everyone knows who is saying what.

I have a very basic multi-user chat server-client system I got working as part of a larger project. I could probably excise the chat-room functionality and post it somewhere for others to experiment with. My client interface uses SFGUI rather than the console, however, so I'm not sure if that would just confuse matters even more for someone new to SFML who just wants a network example.