ecore/ecore_con - Ecore_Con examples (server and client).

SVN revision: 61297
This commit is contained in:
Rafael Antognolli 2011-07-12 14:37:22 +00:00
parent 4ef10c3b53
commit 6c645fa930
4 changed files with 444 additions and 1 deletions

View File

@ -11,6 +11,9 @@
* @li @ref ecore_fd_handler_example_c
* @li @ref ecore_poller_example_c
* @li @ref ecore_con_lookup_example_c
* @li @ref ecore_con_url_download_example_c
* @li @ref ecore_con_server_simple_example_c
* @li @ref ecore_con_client_simple_example_c
*
*/
@ -592,6 +595,172 @@
* @until }
*/
/**
* @page ecore_con_server_simple_example_c Ecore_Con - Creating a server
*
* In this example we are going to create a server that listens for connections
* from clients through a TCP port. You can get the full source code at @ref
* ecore_con_server_simple_example.c.
*
* We begin our example in the main function, to demonstrate how to setup
* things, and then go to the callbacks that are needed for it to run properly.
*
* In the @c main function, after initializing the libraries, we use
* ecore_con_server_add() to startup the server. Look at the reference
* documentation of this function: it supports many types of server, and we are
* going to use #ECORE_CON_REMOTE_TCP (a TCP based server). Other arguments to
* this function are the address where we are listening on, the port, and a data
* pointer that will associate that data with the server:
*
* @dontinclude ecore_con_server_simple_example.c
* @skip main(void)
* @until exit
*
* Notice that we are listening only on 127.0.0.1, which is the internal
* loopback interface. If the server needs to listening on all of its ips, use
* 0.0.0.0 instead.
*
* We also need to set event handlers to be called when we receive any data from
* the clients, when a new client connects to our server, or when a client
* disconnects. These callbacks are:
*
* @until CLIENT_DATA
*
* More details about what these callbacks do will be given later.
*
* Now, before running the main loop, we also want to set some limits to our
* server. To avoid it to be overloaded with too many connections to handle, we
* are going to set a maximum of 3 clients connected at the same time. This
* number is used just to demonstrate the API. A good number to be used here
* would need to be determined by tests done on the server, to check the load
* supported by it.
*
* Any other client trying to connect to this server, after the limit is
* reached, will wait until one of the connected clients disconnect and the
* server accepts the new connection.
*
* Another important thing to do is setting a timeout, to avoid that a client
* hold a connection for too long without doing anything. This timeout will
* disconnect the idle client, allowing that other clients that may be waiting
* to connect finally can do it.
*
* Then we just start the main loop:
*
* @until main_loop_begin
*
* After exiting the main loop, we print the list of connected clients, and also
* free the data associated with each respective client. This data was
* previously associated using ecore_con_client_data_set():
*
* @until }
*
* Then before exiting we show the total uptime of the server:
*
* @until uptime
*
* Now let's go back to the used callbacks.
*
* The first callback, @c _add, is registered to the event
* #ECORE_CON_EVENT_CLIENT_ADD, which will be called whenever a client connects
* to the server.
*
* This callback will associate a data structure to this client, that will be
* used to count how many bytes were received from it. It also prints some info
* about the client, and send a welcome string to it. ecore_con_client_flush()
* is used to ensure that the string is sent immediately, instead of be
* bufferized.
*
* A timeout for idle specific for this client is also set, to demonstrate that
* it is independent of the general timeout of the server.
*
* Before exiting, the callback will display a list of all clients still
* connected to this server. The code for this callback follows:
*
* @dontinclude ecore_con_server_simple_example.c
* @skip Eina_Bool
* @until CALLBACK_RENEW
* @until }
*
* The second callback is @c _del. It is associated with
* #ECORE_CON_EVENT_CLIENT_DEL, and is called whenever a client disconnects from
* this server.
*
* It will just print some information about the client, free the associated
* data structure, and call ecore_con_client_del() on it before exiting the
* callback. Here's its code:
*
* @until CALLBACK_RENEW
* @until }
*
* The last callback will print any data received by this server from its
* clients. It also increments the "bytes received" counter, sdata, in the
* data structure associated with this client. The callback code follows:
*
* @until CALLBACK_RENEW
* @until }
*
* The important parts of this example were described above. If you need to see
* the full source code for it, there's a link to the code in the beginning of
* this page.
*
* @note This example contains a serious security flaw: it doesn't check for the
* size of data being received, thus allowing to the string to be exploited in
* some way. However, it is left like this to make the code simpler and just
* demonstrate the API usage.
*/
/**
* @page ecore_con_client_simple_example_c Ecore_Con - Creating a client
*
* Following the same idea as the @ref ecore_con_server_simple_example_c , this
* example will demonstrate how to create a client that connects to a specified
* server through a TCP port. You can see the full source code at @ref
* ecore_con_client_simple_example.c.
*
* Starting from the @c main function, after reading the command line argument
* list and initializing the libraries, we try to connect to the server:
*
* @dontinclude ecore_con_client_simple_example.c
* @skip main(
* @until exit(2)
* @until }
*
* After doing this, everything else in @c main is setting up callbacks for the
* client events, starting the main loop and shutting down the libraries after
* it.
*
* Now let's go to the callbacks. These callbacks are very similar to the server
* callbacks (our implementation for this example is very simple). On the
* @c _add callback, we just set a data structure to the server, print some
* information about the server, and send a welcome message to it:
*
* @dontinclude ecore_con_client_simple_example.c
* @skip Eina_Bool
* @until CALLBACK_RENEW
* @until }
*
* The @c _del callback is as simple as the previous one. We free the data
* associated with the server, print the uptime of this client, and quit the
* main loop (since there's nothing to do once we disconnect):
*
* @until CALLBACK_RENEW
* @until }
*
* The @c _data callback is also similar to the server data callback. it will
* print any received data, and increase the data counter in the structure
* associated with this server:
*
* @until CALLBACK_RENEW
*
* You can see the server counterpart functions of the ones used in this example
* in the @ref ecore_con_server_simple_example_c.
*
* @note This example contains a serious security flaw: it doesn't check for the
* size of data being received, thus allowing to the string to be exploited in
* some way. However, it is left like this to make the code simpler and just
* demonstrate the API usage.
*/
/**
* @example ecore_idler_example.c
* This example shows when @ref Ecore_Idler, @ref Ecore_Idle_Enterer and @ref
@ -652,6 +821,20 @@
* complete example description at @ref ecore_con_url_download_example_c
*/
/**
* @example ecore_con_server_simple_example.c
* Shows how to setup a simple server that accepts client connections and sends
* a "hello" string to them. See the complete example description at @ref
* ecore_con_server_simple_example_c
*/
/**
* @example ecore_con_client_simple_example.c
* Shows how to setup a simple client that connects to a server and sends a
* "hello" string to it. See the complete example description at @ref
* ecore_con_client_simple_example_c
*/
/**
* @example ecore_con_url_headers_example.c
* Shows how to make GET or POST requests using an @ref Ecore_Con_Url object,

View File

@ -30,6 +30,8 @@ SRCS = \
ecore_con_lookup_example.c \
ecore_con_url_headers_example.c \
ecore_con_url_download_example.c \
ecore_con_server_simple_example.c \
ecore_con_client_simple_example.c \
client_bench.c \
server_bench.c \
ecore_con_client_example.c \
@ -63,13 +65,16 @@ pkglib_PROGRAMS += \
ecore_con_lookup_example \
ecore_con_url_headers_example \
ecore_con_url_download_example \
ecore_con_server_simple_example \
ecore_con_client_simple_example \
ecore_thread_example
ecore_animator_example_LDADD = $(ECOREBASELDADD) @EVAS_LIBS@ $(top_builddir)/src/lib/ecore_evas/libecore_evas.la
ecore_con_lookup_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la
ecore_con_url_headers_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la
ecore_con_url_download_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la
#ecore_con_server_simple_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la
ecore_con_server_simple_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la
ecore_con_client_simple_example_LDADD = $(ECOREBASELDADD) $(top_builddir)/src/lib/ecore_con/libecore_con.la
endif

View File

@ -0,0 +1,124 @@
#include <stdio.h>
#include <Ecore.h>
#include <Ecore_Con.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#else
# define __UNUSED__
#endif
struct _Server {
int sdata;
};
Eina_Bool
_add(void *data __UNUSED__, int type __UNUSED__, Ecore_Con_Event_Server_Add *ev)
{
char welcome[] = "hello! - sent from the client";
struct _Server *server = malloc(sizeof(*server));
server->sdata = 0;
ecore_con_server_data_set(ev->server, server);
printf("Server with ip %s, name %s, port %d, connected = %d!\n",
ecore_con_server_ip_get(ev->server),
ecore_con_server_name_get(ev->server),
ecore_con_server_port_get(ev->server),
ecore_con_server_connected_get(ev->server));
ecore_con_server_send(ev->server, welcome, sizeof(welcome));
ecore_con_server_flush(ev->server);
return ECORE_CALLBACK_RENEW;
}
Eina_Bool
_del(void *data __UNUSED__, int type __UNUSED__, Ecore_Con_Event_Server_Del *ev)
{
if (!ev->server)
{
printf("Failed to establish connection to the server.\nExiting.\n");
ecore_main_loop_quit();
return ECORE_CALLBACK_RENEW;
}
struct _Server *server = ecore_con_server_data_get(ev->server);
printf("Lost server with ip %s!\n", ecore_con_server_ip_get(ev->server));
if (server)
{
printf("Total data received from this server: %d\n", server->sdata);
free(server);
}
ecore_con_server_del(ev->server);
ecore_main_loop_quit();
return ECORE_CALLBACK_RENEW;
}
Eina_Bool
_data(void *data __UNUSED__, int type __UNUSED__, Ecore_Con_Event_Server_Data *ev)
{
char fmt[128];
struct _Server *server = ecore_con_server_data_get(ev->server);
snprintf(fmt, sizeof(fmt),
"Received %i bytes from server:\n"
">>>>>\n"
"%%.%is\n"
">>>>>\n",
ev->size, ev->size);
printf(fmt, ev->data);
server->sdata += ev->size;
return ECORE_CALLBACK_RENEW;
}
int main(int argc, const char *argv[])
{
Ecore_Con_Server *svr;
const char *address;
int port = 8080;
if (argc < 2)
{
printf("wrong usage. Command syntax is:\n");
printf("\tecore_con_client_simple_example <address> [port]\n");
exit (1);
}
address = argv[1];
if (argc > 2)
port = atoi(argv[2]);
eina_init();
ecore_init();
ecore_con_init();
if (!(svr = ecore_con_server_connect(ECORE_CON_REMOTE_TCP, address, port, NULL)))
{
printf("could not connect to the server: %s, port %d.\n",
address, port);
exit(2);
}
/* set event handler for server connect */
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, (Ecore_Event_Handler_Cb)_add, NULL);
/* set event handler for server disconnect */
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, (Ecore_Event_Handler_Cb)_del, NULL);
/* set event handler for receiving server data */
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, (Ecore_Event_Handler_Cb)_data, NULL);
/* start client */
ecore_main_loop_begin();
ecore_con_init();
ecore_init();
eina_init();
return 0;
}

View File

@ -0,0 +1,131 @@
#include <stdio.h>
#include <Ecore.h>
#include <Ecore_Con.h>
#ifdef HAVE_CONFIG_H
# include "config.h"
#else
# define __UNUSED__
#endif
struct _Client {
int sdata;
};
Eina_Bool
_add(void *data __UNUSED__, int type __UNUSED__, Ecore_Con_Event_Client_Add *ev)
{
char welcome[] = "hello! - sent from the server";
Ecore_Con_Server *srv;
Ecore_Con_Client *cl;
const Eina_List *clients, *l;
struct _Client *client = malloc(sizeof(*client));
client->sdata = 0;
printf("Client with ip %s, port %d, connected = %d!\n",
ecore_con_client_ip_get(ev->client),
ecore_con_client_port_get(ev->client),
ecore_con_client_connected_get(ev->client));
ecore_con_client_send(ev->client, welcome, sizeof(welcome));
ecore_con_client_flush(ev->client);
ecore_con_client_timeout_set(ev->client, 6);
ecore_con_client_data_set(ev->client, client);
srv = ecore_con_client_server_get(ev->client);
printf("Clients connected to this server:\n");
clients = ecore_con_server_clients_get(srv);
EINA_LIST_FOREACH(clients, l, cl)
printf("%s\n", ecore_con_client_ip_get(cl));
return ECORE_CALLBACK_RENEW;
}
Eina_Bool
_del(void *data __UNUSED__, int type __UNUSED__, Ecore_Con_Event_Client_Del *ev)
{
struct _Client *client;
if (!ev->client)
return ECORE_CALLBACK_RENEW;
client = ecore_con_client_data_get(ev->client);
printf("Lost client with ip %s!\n", ecore_con_client_ip_get(ev->client));
printf("Total data received from this client: %d\n", client->sdata);
printf("Client was connected for %0.3f seconds.\n",
ecore_con_client_uptime_get(ev->client));
if (client)
free(client);
ecore_con_client_del(ev->client);
return ECORE_CALLBACK_RENEW;
}
Eina_Bool
_data(void *data __UNUSED__, int type __UNUSED__, Ecore_Con_Event_Client_Data *ev)
{
char fmt[128];
struct _Client *client = ecore_con_client_data_get(ev->client);
snprintf(fmt, sizeof(fmt),
"Received %i bytes from client %s port %d:\n"
">>>>>\n"
"%%.%is\n"
">>>>>\n",
ev->size, ecore_con_client_ip_get(ev->client),
ecore_con_client_port_get(ev->client), ev->size);
printf(fmt, ev->data);
client->sdata += ev->size;
return ECORE_CALLBACK_RENEW;
}
int main(void)
{
Ecore_Con_Server *svr;
Ecore_Con_Client *cl;
const Eina_List *clients, *l;
eina_init();
ecore_init();
ecore_con_init();
if (!(svr = ecore_con_server_add(ECORE_CON_REMOTE_TCP, "127.0.0.1", 8080, NULL)))
exit(1);
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, (Ecore_Event_Handler_Cb)_add, NULL);
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, (Ecore_Event_Handler_Cb)_del, NULL);
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, (Ecore_Event_Handler_Cb)_data, NULL);
ecore_con_server_timeout_set(svr, 10);
ecore_con_server_client_limit_set(svr, 3, 0);
ecore_main_loop_begin();
clients = ecore_con_server_clients_get(svr);
printf("Clients connected to this server when exiting: %d\n",
eina_list_count(clients));
EINA_LIST_FOREACH(clients, l, cl)
{
printf("%s\n", ecore_con_client_ip_get(cl));
free(ecore_con_client_data_get(cl));
}
printf("Server was up for %0.3f seconds\n",
ecore_con_server_uptime_get(svr));
ecore_con_shutdown();
ecore_shutdown();
eina_shutdown();
return 0;
}