SophiaFramework UNIVERSE 5.3 |
There are three types of classes for socket communication.
Table 16.2. Socket communication classes
Class Name | Description |
---|---|
SFXTCPSocket | Class for the TCP socket communication. This class provides the function to implement both of the TCP client and the TCP server. |
SFXSSLSocket | Class for the SSL socket communication. This class provides the function to implement only the SSL client. |
SFXUDPSocket | Class for the UDP socket communication. This class provides the function to implement both of the UDP client and the UDP server. |
Sending and receiving data using the stream | |
---|---|
In case of the SFXTCPSocket / SFXSSLSocket class, data can be sent and received using the stream. In addition, data can be sent and received using the Write / Read function without the stream. However, in case of the SFXUDPSocket class, data can not be sent and received using the stream. In this case, the SFXUDPSocket::Send / SFXUDPSocket::Receive function will be used for sending and receiving data. |
Setting of the MIF file | |
---|---|
To use the SFXTCPSocket / SFXSSLSocket / SFXUDPSocket class, the network privilege option must be turned on in the MIF file's setting. |
The SFXTCPSocket class provides the functions to implement both of the TCP client and the TCP sever.
In this class, data can be sent and received using the stream.
When the stream is not used, data can be sent and received with the SFXTCPSocket::Write / SFXTCPSocket::Read function.
The TCP client can be implemented by taking the following procedures with the SFXTCPSocket class.
Example 16.12. Implementation of the TCP Client
// get the time from the NTP server // The _socket variable is defined as class member variable since used in the callback function class NetworkTime { private: SFXTCPSocket _socket; SFXBinaryStreamReader _reader; SFXTimer _timer; public: Void Start(Void); // start to connect to the NTP server Void Stop(Void); // stop connecting to the NTP server // declare callback function XALLBACK_DECLARE_SFXTCPSOCKET(OnConnect) XALLBACK_DECLARE_SFXBINARYSTREAMREADER(OnFetch) XALLBACK_DECLARE_SFXTIMER(OnTimer) }; #define NTP_SERVER ("www.example.com:37") #define TIMER_INTERVAL (5000) // start to connect to the NTP server Void NetworkTime::Start(Void) { SFCError error(SFERR_NO_ERROR); // set the NTP server address SFXSocketAddress address(NTP_SERVER); // set the timer callback function _timer.Set(XALLBACK_INTERNAL(OnTimer)); // open socket if ((error = _socket.Open()) == SFERR_NO_ERROR) { // connect to the NTP server // * the connection result will be notified to the OnConnect function if ((error = _socket.Connect(address, XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) { TRACE(">> connecting..."); } else { // if an error occurs, close TCP socket _socket.Close(); } } if (error != SFERR_NO_ERROR) { // if an error occurs // error handling ... // set the timer. after the TIMER_INTERVAL milliseconds, the OnTimer function will be called _timer.Schedule(TIMER_INTERVAL); } return; } // stop connecting to the NTP server Void NetworkTime::Stop(Void) { // finalization _reader.Release(); _socket.Close(); return; } // callback function notified of the connection result XALLBACK_IMPLEMENT_SFXTCPSOCKET(NetworkTime, OnConnect, error) { if (error == SFERR_NO_ERROR) { // get input stream for receiving data from TCP socket if ((error = _socket.GetStreamReader(64, &_reader)) == SFERR_NO_ERROR) { // perform fetch: receive 4 bytes of data from TCP socket into to input stream buffer actually // * the fetch result will be notified to the OnFetch function if ((error = _reader.Fetch(4, XALLBACK_INTERNAL(OnFetch))) == SFERR_NO_ERROR) { TRACE(">> fetching..."); } if (error != SFERR_NO_ERROR) { // if an error occurs // release resource _reader.Release(); } } } if (error != SFERR_NO_ERROR) { // if an error occurs _socket.Close(); } return; } // callback function notified of the fetch result XALLBACK_IMPLEMENT_SFXBINARYSTREAMREADER(NetworkTime, OnFetch, error) { SFXDate date; // date class UInt32 time; if (error == SFERR_NO_ERROR) { // read data as big endian _reader.SetEndian(SFXBinaryStreamReader::ENDIAN_BIG); // read data as the UInt32 type from input stream buffer into the time variable if ((error = _reader.ReadUInt32(&time)) == SFERR_NO_ERROR) { // set value of the SFXDate instance date.Set(time); // adjust time from January 1, 1900 date -= SFXDateDuration::Offset19000101(); // convert time into local time date += SFXDateDuration::LocalTimeOffset(); // output time in specified format TRACE("%s", date.Format("YYYY/MM/DD hh:mm:ss").GetCString()); } } if (error != SFERR_NO_ERROR) { // if an error occurs // error handling ... } // finalization _reader.Release(); _socket.Close(); return; } // timer callback function XALLBACK_IMPLEMENT_SFXTIMER(NetworkTime, OnTimer) { Start(); return; }
Note | |
---|---|
For more details on the above code, see the networktime applet in the Example/networktime folder of the SophiaFramework UNIVERSE package, which supports suspend and resume functions. |
The TCP server can be implemented by taking the following procedures with the SFXTCPSocket class.
The code below is that the TCP client will communicate with the TCP server through loopback.
Example 16.13. Implementation of the TCP server
// The _socket variable is defined as class member variable since used in the callback function SFMTYPEDEFCLASS(MyClass) class MyClass { SFMSEALCOPY(MyClass) public: static SFCInvokerPtr Factory(Void); private: SFXTCPSocket _socket1; // socket for waiting for connection request at the TCP server SFXTCPSocket _socket2; // socker fot communication at the TCP server SFXTCPSocket _socket3; // socker fot communication at the TCP client Void ServerStart(Void); // start the TCP server Void ClientStart(Void); // start the TCP client Void Stop(Void); // stop the TCP server and the TCP client // callback function XALLBACK_DECLARE_SFXTCPSOCKET(/OnBind) XALLBACK_DECLARE_SFXTCPSOCKET(OnListen) XALLBACK_DECLARE_SFXTCPSOCKET(OnAccept) XALLBACK_DECLARE_SFXTCPSOCKET(OnConnect) XALLBACK_DECLARE_SFXTCPSOCKET(OnWrite) XALLBACK_DECLARE_SFXTCPSOCKET(OnRead) }; // start the TCP server Void MyClass::ServerStart(Void) { SFCError error(SFERR_NO_ERROR); TRACE("Start!"); // open the socket for waiting for connection request at the TCP server if ((error = _socket1.Open()) == SFERR_NO_ERROR) { TRACE("Server Socket for Accepting the Client Requests Is Opened!"); // perform binding OnBind(error); } else { // if an error occurs Stop(); TRACE("Fatal Open Error of the Server Socket for Accepting the Client Requests = %d", error); } } // start the TCP client Void chelloworld::ClientStart(Void) { SFCError error(SFERR_NO_ERROR); SFXSocketAddress address(SFXInetAddress::LoopbackInetAddress(), 1024); // address of the TCP sever // * when connecting to the external server, specify its IP address or domain name TRACE("Now, TCP Client Has Started."); if ((error=_socket3.Open())== SFERR_NO_ERROR) { TRACE("Client Socket for Communicating with the Sever Has Opened!"); // connect to the TCP server if ((error = _socket3.Connect(address, XALLBACK_INTERNAL(OnConnect))) == SFERR_NO_ERROR) { TRACE("connecting..."); } else { // if an error occurs TRACE("Fatal Connect Error = %d", error); Stop(); } } else { // if an error occurs Stop(); TRACE("Fatal Client Socket Open Error = %d", error); } return; } // stop the TCP server and the TCP client Void MyClass::Stop(Void) { _socket1.Close(); _socket2.Close(); _socket3.Close(); return; } // callback function notified that binding is ready to be performed XALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnBind, error) { TRACE("Error at the Start of OnBind() = %d", error); SFXSocketAddress address(SFXInetAddress::LoopbackInetAddress(), 1024); // address of the TCP server // * when accepting connection request from the external client, specify SFXInetAddress::AnyInetAddress() if (error == SFERR_NO_ERROR) { switch (error = _socket1.Bind(address)) { case SFERR_NO_ERROR: // perform litening OnListen(error); break; case AEE_NET_WOULDBLOCK: // when binding is blocked // schedule to bind with registering the OnBind callback function // * the OnBind callback function will be called by BREW AEE when data is ready to be sent TRACE("Schedule Bind."); _socket1.ScheduleBind(XALLBACK_INTERNAL(OnBind)); break; default: // if an error occurs Stop(); TRACE("Fatal OnBind Error = %d", error); break; } } else { // if an error occurs Stop(); TRACE("Fatal OnBind Error = %d", error); } return; } // callback function notified that liteninging is ready to be performed XALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnListen, error) { TRACE("Error at the Start of OnListen() = %d", error); SFXSocketAddress address(SFXInetAddress::LoopbackInetAddress(), 1024); // address of the TCP server if (error == SFERR_NO_ERROR) { // perform listening switch (error = _socket1.Listen()) { case SFERR_NO_ERROR: // start the TCP client StartClient(); // perform accepting OnAccept(error); break; case AEE_NET_WOULDBLOCK: // when listening is blocked // schedule to listen with registering the OnListen callback function // * the OnListen callback function will be called by BREW AEE when data is ready to be sent TRACE("Schedule Listen."); _socket1.ScheduleListen(XALLBACK_INTERNAL(OnListen)); break; default: // if an error occurs Stop(); TRACE("Fatal OnListen Error = %d", error); break; } } else { // if an error occurs Stop(); TRACE("Fatal OnListen Error = %d", error); } return; } // callback function notified that accepting is ready to be performed XALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnAccept, error) { TRACE("Error at the Start of OnAccept() = %d", error); if (error == SFERR_NO_ERROR) { switch (error = _socket1.Accept(&_socket2)) { case SFERR_NO_ERROR: // receive data from the TCP client OnRead(error); break; case AEE_NET_WOULDBLOCK: // when accepting is blocked // schedule to accept with registering the OnAccept callback function // * the OnAccept callback function will be called by BREW AEE when data is ready to be sent TRACE("Schedule Accept."); _socket1.ScheduleAccept(XALLBACK_INTERNAL(OnAccept)); break; default: // if an error occurs Stop(); TRACE("Fatal OnAccept Error = %d", error); break; } } else { // if an error occurs Stop(); TRACE("Fatal OnAccept Error = %d", error); } return; } // callback function notified of the connection result XALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnConnect, error) { TRACE("Error at the Start of OnConnect() = %d", error); switch (error) { case SFERR_NO_ERROR: // succeed to connect TRACE("Connected!"); // send data OnWrite(error); break; default: // if an error occurs Stop(); TRACE("Fatal OnConnect Error = %d", error); break; } return; } // callback function notified that data is ready to be sent XALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnWrite, error) { TRACE("Error at the Start of OnWrite() = %d", error); static ACharConst data[] = "hello world!"; UInt32 size = sizeof(data) - 1; if (error == SFERR_NO_ERROR) { // send data to the TCP server switch (error = _socket3.Write(data, &size)) { case SFERR_NO_ERROR: // succeed to send data TRACE("Data has been sent!"); break; case AEE_NET_WOULDBLOCK: // when sending data is blocked // schedule to send data with registering the OnWrite function // * the OnWrite function will be called by BREW AEE when data is ready to be sent TRACE("Schedule Write."); _socket3.ScheduleWrite(XALLBACK_INTERNAL(OnWrite)); break; default: // if an error occurs Stop(); TRACE("Fatal OnWrite Error = %d", error); break; } } return; } // callback function notified that data is ready to be received XALLBACK_IMPLEMENT_SFXTCPSOCKET(MyClass, OnRead, error) { TRACE("Error at the Start of OnRead() = %d", error); SFXBuffer buffer; UInt32 size(1024); buffer.SetSize(size); if (error == SFERR_NO_ERROR) { // receive data from the TCP client switch (error = _socket2.Read(buffer.GetBuffer(), &size)) { case SFERR_NO_ERROR: // succeed to receive data TRACE("Data has been reveived!"); // display the received data on BREW Output Window buffer.SetSize(size + 1); buffer[buffer.GetSize() - 1] = '\0'; TRACE("Received Data: %s", SFXAnsiString(buffer).GetCString()); Stop(); break; case AEE_NET_WOULDBLOCK: // when receiving data is blocked // schedule to receive data with registering the OnRead callback function // * the OnRead callback function will be called by BREW AEE when data is ready to be sent TRACE("Schedule Read."); _socket2.ScheduleRead(XALLBACK_INTERNAL(OnRead)); break; default: // if an error occurs Stop(); TRACE("Fatal OnRead Error = %d", error); break; } } return; }
When the client and the server are not on the same device | |
---|---|
When the client and the server are not on the same device, implement the TCP client and the TCP server as follows:
|
The SFXSSLSocket class provides the functions to implement the SSL client only.
In this class, data can be sent and received using the stream.
When the stream is not used, data can be sent and received with the SFXSSLSocket::Write / SFXSSLSocket::Read function.
The SSL client can be implemented by taking the following procedures with the SFXSSLSocket class.
Example 16.14. Implementation of the SSL Client
// *** segments different from TCP are in bold // The _socket variable is defined as class member variable since used in the callback function class MyClass { private: SFXSSLSocket _socket; SFXAnsiStringStreamWriter _writer; // output stream SFXAnsiStringStreamReader _reader; // input stream public: Void Start(Void); // callback functions XALLBACK_DECLARE_SFXSSLSOCKET(OnConnect) XALLBACK_DECLARE_SFXSSLSOCKET(OnNegotiate) XALLBACK_DECLARE_SFXANSISTRINGSTREAMWRITER(OnFlush) XALLBACK_DECLARE_SFXANSISTRINGSTREAMREADER(OnFetch) }; Void MyClass::Start(Void) { SFCError error; SFXSocketAddress host("www.example.com:995"); // open SSL socket if ((error = _socket.Open()) == SFERR_NO_ERROR) { // connect to www.example.com:443 // *1 the connection result will be notified to the OnConnect function // *2 host name is automatically resolved error = _socket.Connect(host, XALLBACK_INTERNAL(OnConnect)); } if (error != SFERR_NO_ERROR) { // if an error occurs _socket.Close(); } return; } // callback function notified of the connection result XALLBACK_IMPLEMENT_SFXSSLSOCKET(MyClass, OnConnect, error) { if (error == SFERR_NO_ERROR) { // perform SSL Negotiation with server // * result of SSL negotiation will be notified to the OnNegotiate function error = _socket.Negotiate(XALLBACK_INTERNAL(OnNegotiate)); } if (error != SFERR_NO_ERROR) { // if an error occurs _socket.Close(); } return; } // callback function notified of result of SSL negotiation XALLBACK_IMPLEMENT_SFXSSLSOCKET(MyClass, OnNegotiate, error) { static AChar message[] = "GET / HTTP/1.0\r\n\r\n"; if (error == SFERR_NO_ERROR) { // get output stream for sending data to SSL socket (buffer size: 1024) if ((error = _socket.GetStreamWriter(1024, &_writer)) == SFERR_NO_ERROR) { // write data from the message variable into output stream buffer if ((error = _writer.Write(message, lengthof(message))) == SFERR_NO_ERROR) { // perform flush: send data from output stream buffer to SSL socket actually // * the flush result will be notified to the OnFlush function error = _writer.Flush(XALLBACK_INTERNAL(OnFlush)); } if (error != SFERR_NO_ERROR) { // if an error occurs _writer.Release(); } } } if (error != SFERR_NO_ERROR) { // if an error occurs _socket.Close(); } return; } // callback function notified of the flush result XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMWRITER(MyClass, OnFlush, error) { // release output stream since all data is sent _writer.Release(); if (error == SFERR_NO_ERROR) { // get input stream for receive data from SSL socket (buffer size: 1024) if ((error = _socket.GetStreamReader(1024, &_reader)) == SFERR_NO_ERROR) { // perform fetch: receive data from SSL socket to input stream buffer actually // * the fetch result will be notified to the OnFetch function if ((error = _reader.Fetch(XALLBACK_INTERNAL(OnFetch))) != SFERR_NO_ERROR) { // if an error occurs _reader.Release(); } } } if (error != SFERR_NO_ERROR) { // if an error occurs _socket.Close(); } return; } // callback function notified of the fetch result XALLBACK_IMPLEMENT_SFXANSISTRINGSTREAMREADER(MyClass, OnFetch, error) { SFXAnsiString string; if (error == SFERR_NO_ERROR) { // read data from input stream buffer into the string variable _reader >> string; // display the received data on BREW Output Window TRACE("%s", string.GetCString()); } // release input stream since all data is received _reader.Release(); // close SSL socket _socket.Close(); return; }
The SFXUDPSocket class provides the functions to implement both of the UDP client and the UDP sever.
In this class, data cannot be sent nor received using the stream. Instead, data can be sent and received with the SFXUDPSocket::Send / SFXUDPSocket::Receive function.
The UDP client can be implemented by taking the following procedures with the SFXUDPSocket class.
The UDP server can be implemented by taking the following procedures with the SFXUDPSocket class.
Note | |
---|---|
The UDP sever can send data to another UDP server as the UDP client. |
Example 16.15. Implemetation of the UDP server with the UDP client's function
// The _socket variable is defined as class member variable since used in the callback function class MyClass { private: SFXUDPSocket _socket; public: Void Start(Void); // callback functions XALLBACK_DECLARE_SFXUDPSOCKET(OnBind) XALLBACK_DECLARE_SFXUDPSOCKET(OnSend) XALLBACK_DECLARE_SFXUDPSOCKET(OnReceive) }; Void MyClass::Start(Void) { SFCError error; // open UDP socket if ((error = _socket.Open()) == SFERR_NO_ERROR) { // bind local IP address and port number to UDP socket OnBind(SFERR_NO_ERROR); } return; } // callback function notified that binding is ready to be performed XALLBACK_IMPLEMENT_SFXUDPSOCKET(MyClass, OnBind, error) { SFXSocketAddress address(SFXInetAddress::LoopbackInetAddress(), 1024); // check whether or not an error occurs if (error == SFERR_NO_ERROR) { error = _socket.Bind(address); switch (error) { case SFERR_NO_ERROR: // send data asynchronously OnSend(SFERR_NO_ERROR); break; case AEE_NET_WOULDBLOCK: // schedule to perform binding: register the OnBind callback function // * the OnBind callback function will be called by BREW AEE when binding is ready to be performed _socket.ScheduleBind(XALLBACK_INTERNAL(OnBind)); break; } } return; } // callback function notified that data is ready to be sent XALLBACK_IMPLEMENT_SFXUDPSOCKET(MyClass, OnSend, error) { static ACharConst data[] = "udp!"; SFXSocketAddress address(SFXInetAddress::LoopbackInetAddress(), 1024); UInt32 size; // check error if (error == SFERR_NO_ERROR) { size = sizeof(data) - 1; // send data error = _socket.Send(address, data, &size); switch (error) { case SFERR_NO_ERROR: // check whether data of specified size is written or not // SFXUDPSocket::Send function may not send data of specified size at a time // here for simple explanation, display error message if (size == sizeof(data) - 1) { // receive data asynchronously OnReceive(SFERR_NO_ERROR); } else { TRACE("...failed to send ..."); } break; case AEE_NET_WOULDBLOCK: // if sending data is blocked // schedule to send data: register the OnSend callback function // * the OnSend callback function will be called by BREW AEE when data is ready to be sent _socket.ScheduleSend(XALLBACK_INTERNAL(OnSend)); break; } } return; } // callback function notified that data is ready to be received XALLBACK_IMPLEMENT_SFXUDPSOCKET(MyClass, OnReceive, error) { SFXSocketAddress socket; SFXBuffer buffer; UInt32 size; // check error if (error == SFERR_NO_ERROR) { buffer.SetSize(4); size = static_cast<UInt16>(buffer.GetSize()); // receive data switch (_socket.Receive(&socket, buffer.GetBuffer(), &size)) { case SFERR_NO_ERROR: // check whether data of specified size is read or not // SFXUDPSocket::Receive function may not receive data of specified size at a time // here for simple explanation, display error message if (size == buffer.GetSize()) { // display received data buffer.SetSize(buffer.GetSize() + 1); buffer[buffer.GetSize() - 1] = '\0'; TRACE(":%s", SFXAnsiString(buffer).GetCString()); // close socket _socket.Close(); } else { TRACE("...failed to receive..."); } break; case AEE_NET_WOULDBLOCK: // if receiving data is blocked // schedule to receive data: register the OnReceive callback function // * the OnReceive callback function will be called by BREW AEE when data is ready to be received _socket.ScheduleReceive(XALLBACK_INTERNAL(OnReceive)); break; } } return; }
Copyright(c) 2002 - 2024 Sophia Cradle Incorporated All Rights Reserved. |