Multiple clients

Helllo!
It's possible for multiple clients connect to yun's server (for TCP connection), that all work in the same time? Establish many connections simultaneously?

In general yes. If by "yun server" you mean the web server, by default the max number of requests allows is 2 (but you can customize the number by editing /etc/config/uhttpd)

This question appears when i read library reference. In class YunServer there is a method YunServerWrite. Description says: "Write data to all the clients connected to a server". So i tried to establish simulteneous connection to Yun with two different client devices (smartphone and tablet with installed TCPClient android App). I successfuly connected to the server, but data exchange goes only between Yun and device, that first establish connection. Second just write, that it is connected, but don't recieve any data. In a meen time, scatch in Yun must pereodicly send data using YunServerWrite method, but receiveng only happens on first connected device. So, question goes like this, it possible do something, that i can receive data with both devices?

I am having the same issue. I think it has to do with the line:

Yunclient client = server.accept();

Once the second device connects, the old connection is taken over.
Is there a way to dynamically name clients so that this wont happen ?

@Gunnisilli,

please post your issues in a new thread (NEW TOPIC). And describe your problem in full.

Thanks
Jesse

I don't have a separate problem. My question is: Can a Yun Server host more than one client at a time? And how would you go about doing that.

I have searched quite a bit and have yet to find an example of anyone doing that.

Thanks for the help :slight_smile:

Gunnisilli:
My question is: Can a Yun Server host more than one client at a time?

Yes.

And how would you go about doing that.

By maintaining separate YunClient objects for each connection.

// Yun Dual Client Test

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

YunServer server(23); // Listen on port 23 - standard Telnet

// Define the simultaneous clients
YunClient client1;
YunClient client2;


void setup()
{
  Bridge.begin();
  
  Serial.begin(19200);
  while (!Serial)
    ;  // Wait until a Serial Monitor is connected.

  server.noListenOnLocalhost(); // Listen for external connections
  server.begin();
  
  // Create the initial client objects, whether connected or not.
  client1 = server.accept();
  client2 = server.accept();
}


void loop()
{
  // Try to process both clients
  processClient(&client1, "Client1");
  processClient(&client2, "Client2");
}



void processClient(YunClient* client, String clientName)
{
  // Is the client connected? If not, try to connect.
  if (!client->connected())
  {
    // Try to accept a connection
    *client = server.accept();
    
    // If now connected, notify of new connection
    if (client->connected())
      Serial.println(clientName + ": new connetionn");
  }
  
  // Is the client now connected? If so, process I/O
  if (client->connected())
  {
    String str = "";
    
    // Read all available data, append to string
    while (client->available())
      str = str + (char)client->read();

    // Trim off non-printable characters.
    str.trim();

    // Got something? If so, print out what was recevied, send client name back to other side
    if (str.length() > 0)
    {
      Serial.println(clientName + ": received \"" + str + "\"");
      client->println(clientName);
    }
  }
}

I just threw together this code as an example, I don’t profess that this is the ideal solution.

This code manages two YunClient objects, so it can handle two simultaneous connections. It waits for a Telnet connection, and when one is made it prints out a new connection message on the serial port with the client’s name. It then listens for any incoming data. When data is received, it echos it to the the serial port, and sends the client’s name back on the client connection.

I tested it by loading the script, and then connecting to the Yun with a Telnet client. Whatever I typed at the client Telnet session was output on the serial monitor with the correct client name, and the client name was echoed back to the telnet client. I made multiple connection and disconnection attempts, including two clients connected at once, and it always kept track of the proper connection and didn’t get the two clients confused as reported in reply #2 of this thread.

The general idea of the sketch is that there are two pre-defined client objects. They are initialized as valid client objects at the end of setup() by calling server.accept() for both of these. This is important so that the first calls to client.connected() will work. If the initial accept() attempt is not made, then there will not be a valid client object for that first connected() call and it will fail. So even if there are no waiting connections to be accepted, those first calls must be made. (Odds are that they will not be connected at this point.)

loop() simply tries to process each client in turn.

The real meat is in processClient(). Note that this takes a pointer to the client, rather than the client itself. This is so it can return a new client back into that pointer when a new connection is made. The function first checks if the client is connected: if not, server.accept() is called to check for a new connection. If there is now a connection, it is a new connection, and any special processing is done. In this case, it just prints out a message that there is a new connection. Other applications may need to do something special to further set up a new connection.

The next thing that processClient() does is another connected() check. This could be an else clause of the first test, but if so it would not try to process any client I/O until the next pass through processClient(). By making it a separate IF statement, it will be processed immediately after the connection is established, even if the two IF statements appear redundant. So, if the client is connected, any IO operations on the active client can be performed here. This example just reads and echos any waiting data. When processing the client, it’s important to not spend any more time here than necessary, or it will interfere with the other client(s). In other words, no lengthy delays, and no waiting for a particular input sequence to complete: get in, process what you can, and get out. Any additional processing will have to wait until the next call of processClient().

This sketch uses a rather simple way of tracking two clients. This could be expanded to more clients by declaring more client instances, and calling processClient() for each in loop(). Or a more sophisticated means of tracking the clients using a dynamic array of client objects could be implemented. This would periodically try to connect a client, and if a connection is made it would be added to the array of current clients. Then, iterate over the array of clients to give each a chance to be processed. Code would also be needed to check if an existing client on the array had closed the connection so it could be disposed and cleaned up. If getting into something this sophisticated, it would probably be best to wrap it all up in a manager object.

And of course, the actual processing of the clients could be made as sophisticated as needed. I only did some simple echoing of data to prove the concept. And different a port number could be used according to the needs of the application.

Thank you ShapeShifter! What a great reply! Now I have loads to try out.

You're welcome, good luck!

It should be pointed out that which client gets the first connection is pretty much random. Don't expect the first connection to always be on client1. If the connection comes in while calling processClient() for client1, but after the accept call is made, then it will be picked up by client2. It will be pure chance.