I want to write a C + + library under Linux--remember my C + + libraries design process: Design a TCP service program

Source: Internet
Author: User

I want to write a C + + library under Linux to implement some common functions.
My first thought was to implement a TCP listener. What functions should the program have?
1: Start/Stop monitoring
2: Notifies the caller when there is a client connection
3: Notifies the caller when disconnected from the client
4: Notifies the caller when a message arrives

5: Try to avoid the program exit when there is no close socket.


The general interface and structure of the program are mainly represented by a class, and the contents are as follows:
#pragma once#include <functional>namespace hi{/** @ Brief TCP listener sends notification */class tcpevent{public:/* Brief Client Connection successful notification, * Parameters are socket descriptor, remote IP, remote port, local IP, local port */std::function<void (int,const char*, unsigned short,const char*,unsigned Short) > on_open_;/* Brief Client Connection disconnect notification */std::function<void (int) > on_close_;/* Brief receiving client message notification */std::function <void (int) > on_receive_;};/ * * @ Brief TCP Listener Class */class hitcpserver{public:/** @brief start listening * @param [in] evt notification object * @param [in] Port simplified port * @param [in] IP supervisor Listen IP, if empty, indicates listening for all ip* @retval true: Success, false: Failed */bool open (const tcpevent& EVT, unsigned short port, const char* IP = NULL);/** @brief Stop listening * @retval true: Success; false: Failed */bool close ();};}


This is the initial interface of the TCP listener that I think of (assuming that hitcpserver is placed in the HiTcpServer.h file in the Net Folder).
How to use it? The test code is as follows:
#pragma once#include <string> #include <sys/socket.h> #include <iostream> #include "net/ HiTcpServer.h "using namespace std;//client connection succeeded static void On_client_open (int sock,const char* remote_ip, unsigned short rem Ote_port,const char* local_ip,unsigned short local_port) {cout<< "Accept a client connect,socket[" <<sock << "] remote[" <<remote_ip<< "," <<remote_port<< "]local[" <<local_ip<< "," <<local_port<< "]" &LT;&LT;ENDL;} Received client message static void On_client_recv_data (int sock) {char rece_buf[256];memset (rece_buf, 0, n); int = recv (sock, Rece_ BUF, 0);cout<< "Receive Client (socket:" <<sock<< ") Data,len:" <<n<<endl;} Client connection disconnects the static void On_client_close (int sock) {cout<< "Client (socket:" <<sock<< ") is close" << Endl;} void Main () {hi::tcpevent Evt;evt.on_open_ = Std::bind (&on_client_open); evt.on_close_ = Std::bind (&on_client_ close); evt.on_receive_ = Std::bind (&on_cLient_recv_data); Hi::hitcpserver Server;server.open (EVT, 6000); sleep (60);}


This is the initial idea.


The Tcpevent::on_open_ function has a bit more parameters, and it is estimated that each connection has a remote address and a local address, which is abstracted as
A class is more appropriate, and the class can be called Socketchannel.


Specific definition (for simplicity, you can put it in hiTcpServer.h):
/** @brief Socket Channel Information class */class Socketchannel{public:socketchannel (): Sock_ ( -1), Remote_port_ (0), Local_port_ (0) {} public:intsock_;///< socket File Descriptor std::string remote_ip_;///<-to-end ipunsigned short remote_port_;///<-to-end Port std:: String local_ip_;///< local ipunsigned short local_port_;///< Local Port};


The definition of Tcpevent::on_open_ is as follows:
Std::function<void (bool,int,socketchannel&) > On_open_;
The revised hitcpserver is:
#pragma once#include <functional>namespace hi{/** @brief Socket Channel Information class */class Socketchannel{public:socketchannel (): Sock_ ( -1), Remote_port_ (0), Local_port_ (0) {}public:intsock_;///< socket file descriptor std::string remote_ip_;///< ipunsigned Short remote_port_;///<-to-end port std::string local_ip_;///< local ipunsigned short local_port_;///< local port };/** @ Brief TCP listener sends notification */class tcpevent{public:/* Brief Client Connection successful notification */std::function<void (int,socketchannel&) > on_open_;/* Brief Client Connection disconnect notification */std::function<void (int) > on_close_;/* Brief receiving client message notification */std::function< void (int) > on_receive_;};/ * @ Brief logic Implementation Class */class tcpserverimpl;/** @ Brief TCP Listener Class */class hitcpserver{public:hitcpserver (); ~hitcpserver ();    hitcpserver& operator = (const hitcpserver&) = delete; Hitcpserver (const hitcpserver&) = delete;public:/** @brief Start listening * @param [in] evt notification object * @param [in] Port listening port * @param [ In] IP listener IP, if empty, indicates that all ip* @retval true: Success; false: Failed */bool open (const tcpevent& EVT, Unsigned short port, const char* IP = NULL),/** @brief Stop listening * @retval true: Success; false: Failure */bool close ();p rivate:tcpserverimpl* Imp l_;/* brief implements the logical pointer */};}


In the new hiTcpServer.h, in addition to adding the Socketchannel class, modified the Tcpevent::on_open_ parameters, but also added Tcpserverimpl
Pointer, and declares the constructor.
Hitcpserver's Impl_ variable is primarily responsible for implementing the program logic.
Hitcpserver copy constructors and assignment pointers are deleted to prevent the creation of Hitcpserver objects from being copied.


Another look at hiTcpServer.h feeling a bit complicated, socketchannel,tcpevent here a bit messy,
And it is likely to be used when implemented, so it needs to be removed from the HiTcpServer.h and written to another header file
HiNetCommon.h in the (net).
The new program:
HiNetCommon.h:
#pragma once#include <functional> #include <string> #include <netinet/in.h>namespace hi{/** @brief Socket channel Information class */class Socketchannel{public:socketchannel (): Sock_ ( -1), Remote_port_ (0), Local_port_ (0) {}public: intsock_;///< socket File Descriptor std::string remote_ip_;///<-to-end ipunsigned short remote_port_;///<-to-end port std::string local_ip_;///< local ipunsigned Short local_port_;///< local Port};/** @ Brief TCP listener sends notifications */class Tcpevent{public:tcpevent ();p ublic:/* Brief Client Connection successful notification */std::function<void (int,socketchannel&) > on_open_;/* Brief Client Connection Disconnect notification */STD:: function<void (int) > on_close_;/* Brief receive client message notification */std::function<void (int) > On_receive_;};}


HiTcpServer.h:
#pragma once#include "Net/hinetcommon.h" namespace hi{/* @ Brief logic Implementation Class */class tcpserverimpl;/** @ Brief TCP listener class */class HITC Pserver{public:hitcpserver (); ~hitcpserver (); hitcpserver& operator = (const hitcpserver&) = delete;    Hitcpserver (const hitcpserver&) = delete;public:/** @brief Start listening * @param [in] evt notification object * @param [in] Port listening port * @param [ In] IP listener IP, if empty, indicates listening for all ip* @retval true: Success, false: Failed */bool open (const tcpevent& EVT, unsigned short port, const CHA r* IP = NULL);/** @brief Stop listening * @retval true: Success, false: Failed */bool close ();p rivate:tcpserverimpl* impl_;/* Brief Implement the logical pointer */};}


Test procedure:
#pragma once#include <string> #include <sys/socket.h> #include <iostream> #include "net/ HiTcpServer.h "using namespace std;//client connection succeeded static void On_client_open (int sock,hi::socketchannel& channel) {cout << "Accept a client connect,socket[" <<sock<< "remote[" <<channel.remote_ip<< "," < <channel.remote_port<< "]local[" <<channel.local_ip<< "," <<channel.local_port<< " ] "&LT;&LT;ENDL;} Received client message static void On_client_recv_data (int sock) {char rece_buf[256];memset (rece_buf, 0, n); int = recv (sock, Rece_ BUF, 0);cout<< "Receive Client (socket:" <<sock<< ") Data,len:" <<n<<endl;} Client connection disconnects the static void On_client_close (int sock) {cout<< "Client (socket:" <<sock<< ") is close" << Endl;} void Main () {hi::tcpevent Evt;evt.on_open_ = Std::bind (&on_client_open); evt.on_close_ = Std::bind (&on_client_ close); evt.on_receive_ = Std::bind (&on_client_recv_data); Hi::hitcpserver sErver;server.open (EVT, 6000); sleep (60);} 


The Hitcpserver class looks relatively simple, but I'm not going to implement Hitcpserver
Because its implementation is not as simple as it seems, it involves the interception of sockets and the distribution of IO events. So there are other programs that need support.
I'm going to add two classes Hitcplisten and Hitcpepoll decibels to enable the socket listener and IO event distribution.


Next 1:
1: The library can only be compiled with GCC that supports c++11
2: To the STL is not familiar with the caller, need to understand the knowledge points are: Function,bind,delete function (c++11 new feature)
3: Actually I also want to add the Hitcpserver and tcpevent to prevent the class from being inherited,
But I do not have a good way to implement such a function. It is best not to derive subclasses from Hitcpserver and tcpevent if you want callers.
4: In the original version of Hitcpserver, there were three overloaded open functions, and finally I adjusted the order of the parameters (an empty IP
Adjusted to the last), combining three functions into one, the overall sense of the Opend function's parameter order is a bit weird.
5: In this interface, I try to avoid using class inheritance to implement the function extension.
6: In order to keep it simple and clear, I did not have any processing of the socket file descriptor directly exposed to the caller, feeling that this is more friendly to the caller.
7: Remote address and local address can actually be conveniently obtained through socket file descriptor, so feel Tcpevent::on_open_
The second parameter is a bit redundant, and the interface may be modified in a later version. If this is true, a socket file descriptor is added to get
The interface of the relevant information, or the user directly with Getpeername and GetSockName also line.
"The Art of Unix Programming", emphasizing "thin glue layer", now tcpevent::on_open_ seems to violate this principle.
8: In my initial thinking, Hitcpserver::open has three function parameters, respectively, corresponding to the Tcpevent
Three member variables, I think hitcpserver::open parameters a little more, just abstract out tcpevent.


Limit:
The 1:hitcpserver class restricts the freedom of the user to choose the IO multiplexing mechanism, and the freedom to start the socket monitoring, even when the network is poor.
Processing is not supported.




I want to write a C + + library under Linux--remember my C + + libraries design process: Design a TCP service program

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.