This quick start guide will use IPv6/UDP sockets to demonstrate basic conexus concepts.
buf
and count
parameters in the POSIX write()
function: ssize_t write(int fd, const void *buf, size_t count);
read()
method which is similar in concept to the POSIX read()
operation. However, a Conexus::Endpoint also provides start()
and stop()
methods. When a Conexus::Endpoint is started it will create a separate service thread. This thread will watch for input data and emit signal_data
when data is received by the endpoint.signal_data
to the function or class method you want to receive the data. Since data is delivered via a sigc++ signal you can connect multiple functions and/or class methods and all connected callbacks will receive the endpoint's data.signal_data
signal.void
function_or_method_name
(const Conexus::Data
)void
and the first parameter must be const
Conexus::Data
sigc::bind
, which is discussed in the Gtkmm tutorial and the sigc++ documentation.sigc::mem_fun
and sigc::ptr_fun
will sufficesigc::slot<void
, Conexus::Data>
signal_data()
method to access the data signal. You will use the signal's connect()
method to accomplish this.tr1
(Technical Report 1), which as of this writing has been accepted by the committee and recommended to ISO for incorporation as the first revision to the C++ standard. A reference implementation can be found in the boost library or in the std::tr1
namespace of gcc 4.0 or greater.pointer
typedef and the create
method defined in each conexus class.pointer
typedef is defined within each class and is typedefed to a smart pointer to that specific class. Thus, Conexus::IPv6::UDP::pointer
is a smart pointer to an IPv6/UDP endpoint, and Conexus::TTY::pointer
is a smart pointer to a TTY endpoint.create()
methods with parameters that are identical to the class' constructors. The create()
method dynamically creates an object and returns a smart pointer to that object (the typedefed pointer
), similar to the way the new
operator dynamically creates an object and returns a raw pointer to the newly created object. Since the create()
method is static, you do not need an instance of the class to call it; Classname::create()
is sufficient.create()
can be assigned to the class' pointer
type, which allows you to use a syntax such as: Classname::pointer my_variable = Classname::create();
#include <conexus.h> int main(int argc, char* argv[]) { const char* data = "0123456789"; Conexus::init(); Conexus::IPv6::UDP::pointer udp = Conexus::IPv6::UDP::create(); udp->set_remote_address("::1", 1500); udp->write( data, 11 ); return 0; }
#include <conexus.h> int main(int argc, char* argv[]) {
const char* data = "0123456789";
init()
method which will take care of various initializations including the threading system. pointer
typedef in the Conexus::IPv6::UDP
class, and also calls upon the static method create()
in the same class to actually create the endpoint. We use the pointer
typedef since the return value from the create()
method is always a smart pointer to that class type.writeto()
method. However, for this example we will use the basic write()
method present in Conexus::Endpoint (ancestor of our udp class).writeto()
method accepts the address as a parameter, the write()
method requires the remote address to already be set, so we will do that now. udp->set_remote_address("::1", 1500);
udp->write( data, 11 );
main()
and the closing brace. return 0;
}
stdout
as a C string. It will run for 20 seconds then automatically shut-down.#include <conexus.h> #include <iostream> #include <unistd.h> void print_data(const Conexus::Data d); int main(int argc, char* argv[]) { Conexus::init(); Conexus::IPv6::UDP::pointer udp = Conexus::IPv6::UDP::create(1500); udp->signal_data().connect(sigc::ptr_fun(&print_data)); udp->start(); sleep(20); udp->stop(); return 0; } void print_data(const Conexus::Data d) { std::cout << "Received " << d.size() << " bytes of data: " << (const char*)(d.data()) << "\n"; }
cout
we will need to include iostream
. Finally, since we call the sleep()
function we will also need to include unistd.h
. #include <conexus.h> #include <iostream> #include <unistd.h>
void
return type and the first parameter must be a const
Conexus::Data
type. void print_data(const Conexus::Data d);
init()
method. int main(int argc, char* argv[]) { Conexus::init();
Conexus::IPv6::UDP::pointer udp = Conexus::IPv6::UDP::create(1500);
print_data()
to the endpoint's data signal. We use the signal_data()
accessor to get the signal, and then use the signal's connect()
method. The connect()
method in the sigc++ library takes a sigc++ slot as its parameter. We turn the print_data()
function into a slot by using the sigc::ptr_fun()
class which creates a slot from a pointer to a function (hence ptr_fun
). Thus, our function name is preceeded by the address operator &
. udp->signal_data().connect( sigc::ptr_fun(&print_data) );
print_data()
function. We will start the endpoint using the start()
method. This will create a service thread that will call our print_data()
function as our endpoint receives data. udp->start();
print_data()
in the service thread we will have this main thread sleep for 20 seconds. When you run the example server and client you should start the server, then run the client several times. You will see that the service thread is responding to your client while the main thread is sleeping at this point. sleep(20);
udp->stop();
main
and to include the closing brace. return 0;
}
print_data()
function. This is a one line function that adds a little helper text and prints out the number of bytes received and the actual data as a C style string. void print_data(const Conexus::Data d) { std::cout << "Received " << d.size() << " bytes of data: " << (const char*)(d.data()) << "\n"; }
size()
member and the data is available through the data()
member.
The typecast is necessary since the native data type of the Conexus::Data class is an unsigned 8-bit integer (uint8_t
) which is probably (but not necessarily) a C unsigned
char
type.