📄 io.h
字号:
* functions. The class will make sure that the application * will only recieve data from one client at a time, but * make sure that the server is not blocked, waiting for * the application to read data from the client. This is done * with a special @ref SocketBuffer class, that ensures * that data received is kept in a by client socket, buffer. * The threaded IO class, will then monitor the application * and delivered to it, the next buffer to read. * * @author Orn E. Hansen <oe.hansen@gamma.telenordia.se> * @short A C++ implementation of a threaded IO class for linux. */ class PthreadIO : public Pthread, public AsynchronousIO { public: enum selectState { /** Activate the read selection */ readSelect_e, /** Activate the exception selection */ excSelect_e, /** Activate the write selection */ writeSelect_e }; private: int _id; SocketBuffer _empty_socket; SocketBuffer* _client; bool _is_socket; bool _do_buffers; struct timeval _timeout; /** * This method, returns the object that is the target for * the asynchronous operation. This can either be this or * another object, set through the register_fd call. * * @return A pointer to the asynchronous object. */ AsynchronousIO *asyncObject(Socket*); protected: typedef std::list<SocketBuffer *> __socklist; typedef std::list<AsynchronousIO *> __iolist; typedef std::list<AsynchronousIO *>::iterator iterator; typedef std::list<SocketBuffer *>::iterator s_iterator; DescriptorSet _active_set; DescriptorSet _except_set; DescriptorSet _avail_set; __iolist _others; __socklist _sock_queue; /** * incoming_connection. * * This function accepts incoming calls, and creates a new client * file descriptor on it. * * The normal function of this method, is to accept SOCK_STREAM * client connections, and must be specifically rewritten to handle * other kinds of conections/messages. */ virtual void incomingConnection(); /** * Time on select. * * The inner select loop, can be set to timeout after a specific * time, if this occurs, this function will get control. * * Such a timeout is only allowed to occur, once. When a timeout * occurs, the timeout values are set to 0, so that no timeout will * reoccur, unless specifically reset inside this method. */ virtual void selectTimeout(); /** * Urgent interrupt. * * This method, is called whenever the thread receives a signal * urgent interrupt. * * Signal urgent, is used within the thread to wake it up on * several occasions to handle situations that need attention. This * is for example the case, whenever a new file descriptor is * registered. In that case, the class will give itself a signal * urgent to break the select loop inside it, and force it to * recognize the new descriptor. * * Since this signal is also used, inside the system. The user * must create his/her own means in deciding which signal urgent * is to be handled by his/her code. * * The system will do this partially, and all urgent interrupts * that occurr when not in asynchronous delivery will be redirected * to the @urgent method. If you do not need to catch the interrupt * itself, but only those situations, use that method instead. */ virtual void signalUrgent(void *); /** * Urgent. * * An urgent interrupt has occurred, and the system has determined * it is not a signal that asynchronous delivery has finished. The * programmer should use this method instead of the above, whenever * possible. */ virtual void urgent(); /** * This is inherited from AsynchronousIO, and will ensure * that the handler is recalled with the given buffer, when it * becomes available. * * @param s Socket buffer to save. */ virtual void queueSocket(SocketBuffer *); /** * When the select loop, tells that there is data available * from a client, this is the routine that will read the * data. The default method, will get as much data as it * can with the 'read' call and store it in the buffer that * is associated with the socket. * * Overwrite this method, if you need a different way to * obtain data from a socket, as would be in an UDP socket * environment. * * @param s Socket that has data available. * @return Actuall bytes read, or -1 on error. */ virtual int fillSocketBuffer(SocketBuffer&); /** * This is the default method for data received. It will * simply throw an error,as it is assumed that people will * want to rewrite this routine. * * @param f Reference to the buffered socket. */ virtual void got(SocketBuffer&); /** * In the case of a server socket, a client connecting to the * machine will create a new file descriptor for that socket. In * this case, the IO thread will call this method with the * file descriptor that is being created. * * @param sd The socket of the client socket. */ virtual void open(Socket&); /** * In the case of a server socket, whenever a client closes the * connection, the IO thread will call this method to tell about * the event. If this method is overwritten, care should be taken * by the programmer, to actuall close the file descriptor, or to * call this original method to perform that task. * * @param sd The socket that is being closed. */ virtual void close(Socket&); /** * When an error occurs, during an input event, the thread will * link in this method to record and manage the error. This is * an exception handling method, that will tell the thread wether * the file descriptor in question should remain open or if it * should be closed as a result of the error. The normal method * associated with this event will close the descriptor. * * @param fd The file descriptor that gave the IO error. * @return True if the file descriptor should be closed, false otherwise. */ virtual bool failure(int); public: /** * This constructor is primarily for the purpose of * making this class a managing class for other file * descriptors. Any file descriptor that needs to be * managed must be passed to the class through the * register_fd(...) method. */ PthreadIO(AsynchronousIO::async_type_t t=AsynchronousIO::dupl_deliver_e); /** * The constructor for the IO class needs to know the fd * to asynchronise input for. The class itself, does not * open an IO base to asynchronize, but relies on the user * to provide for a file descriptor and having set it up * prior to the class creation. Thus, the class can be * used for normal serial io, as well as a more complex * socket io. * * @param fd The file descriptor. */ PthreadIO(int, AsynchronousIO::async_type_t t=AsynchronousIO::dupl_deliver_e); /** * This constructor will create a client socket, at * specified port. In all other matters, it will behave * like the above constructor. * * @param s The name of the machine to connect to. * @param p The port number to connect to on the remote end. * @param styp The socket type to use, default stream. * @param prot The protocol to use, default TCP. */ PthreadIO(const char *,int,AsynchronousIO::async_type_t t=AsynchronousIO::dupl_deliver_e,__socket_type t=SOCK_STREAM,int i=IPPROTO_TCP); /** * This constructor, creates a server socket that is not of * types SOCK_STREAM or SOCK_SEQPACKET. It does not perform a * listen on the socket, but binds it to a port and specifies it * to be a server socket. * * @param p The port to serve. * @param d Delivery mechanism, default duplex delivery. * @param styp The socket type to use, default is datagram. * @param prot The protoc to use, default UDP. */ PthreadIO(int,AsynchronousIO::async_type_t t=AsynchronousIO::dupl_deliver_e,__socket_type t=SOCK_DGRAM,int i=IPPROTO_UDP); /** * This constructor will create a server socket, at * the specified port, with a specified backlog count. In all * other matters, it is identical to the above constructor. * * @param p The port to serve. * @param l The backlog count. * @param d Delivery mechanism, default is duplex delivery. * @param styp The socket type to use, default stream. * @param prot The protocol to use, default TCP. */ PthreadIO(int,int,AsynchronousIO::async_type_t t=AsynchronousIO::dupl_deliver_e,__socket_type t=SOCK_STREAM,int i=IPPROTO_TCP); virtual ~PthreadIO(); /** * Tell the thread, to go through the buffers to see if * any needs to be delivered. * */ void flushBuffers(); /** * This is the thread, that does the IO. It is inherited * from the Pthread class, and should not be changed for * any reason. * * @param x The parameter has no value for this class. */ int thread(void *); /** * Write a single character to the socket passed to the * method. * * This method, accepts a SocketBuffer class as a parameter * and put the given chacter into the socket's associated * output buffer. The character will then be transmitted to * the socket, when writing to the socket will not block the * application. * * @param sd The socket to write to. * @param ch The character to write. * @return The number of bytes written. */ int put(SocketBuffer&,char); /** * This method is the same as above, and differs only in the * parameters it accepts. * * @param sd The socket to write to. * @param s The string to write. * @return The number of bytes written. */ int put(SocketBuffer&,const std::string&); /** * This method is similar to the above, the difference in parameters * is that the file descriptor is removed. The connected * @see fd() * will be written to. * * @param ch The character to write. * @return The number of bytes written. */ int put(char); /** * This method is similar to the above, and differs only in the * parameters it accepts. * * @param s The string to write. * @return The number of bytes written. */ int put(const std::string&); /** * This is a formatted version of the put command, it takes * a format string as a first parameter and then writes the * data to the connected socket. * * @param f The format to use, when writing characters. * @param n Parameters associated with the format. * @return The number of bytes written. */ int putf(const char *, ...); /** * This methos is identical to the one above, except for the * fact that it accepts a SocketBuffer to send the data * to. * * @param sd Socket to write to. * @param f The format to use for data preparation. * @return The number of bytes written. */ int putf(SocketBuffer&, const char *, ...); /** * A single class of this type, can handle more than one * file descriptor. This is not really recommended, but can * come in handy when you don't really want to have several * threads, but want the data to be received by it's own * class. After all, there is a certain amount of overhead * associated with having threads managed by the system. * * This method, will add a file descriptor to the managed * list of descriptor, and will tell the class to send it * to the associated receiver class. Note, that all receiver * classes must inherit * @ref #AsynchronousIO * for this purpose. * * @param p A pointer to the asynchronous input class. * @param i The selection to register to. */ void registerFD(AsynchronousIO *, int i=readSelect_e); /** * When the class no longer needs to manage a certain * file descriptor, it is recommended that it be removed * from the list of managed descriptors through this * method. * * @param p A pointer to the asynchronous input class. * @param i The selection to register from. */ void unregisterFD(AsynchronousIO *, int i=readSelect_e); };};#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -