forked from enlightenment/efl
ecore/ecore_con - Ecore_Con examples (server and client).
SVN revision: 61297
This commit is contained in:
parent
4ef10c3b53
commit
6c645fa930
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue