ACE中ACE_SOCK下ACE_SOCK_Acceptor类解析
来源:互联网 发布:js apply原理 编辑:程序博客网 时间:2024/06/16 10:49
ACE_SOCK_Acceptor,ACE中面对流(有连接)sock编程的接受器类,将服务器端编程的细节,步骤做了包装,让我们不需要再直接的使用OS的复杂,繁多的API函数,那么这个类中到底替我们做了多少呢?我们该如何修改它呢?
首先看类的构造函数:
ACE_SOCK_Acceptor (void);ACE_SOCK_Acceptor (const ACE_Addr &local_sap, int reuse_addr = 0, int protocol_family = PF_UNSPEC, int backlog = ACE_DEFAULT_BACKLOG, int protocol = 0);ACE_SOCK_Acceptor (const ACE_Addr &local_sap, ACE_Protocol_Info *protocolinfo, ACE_SOCK_GROUP g, u_long flags, int reuse_addr, int protocol_family = PF_UNSPEC, int backlog = ACE_DEFAULT_BACKLOG, int protocol = 0);
第三个构造函数比第二个多了三个参数,这个构造函数我们不讨论(超复杂,相信你知道真相也会放弃的)。
第一个是无参,不解释。
第二个构造函数,也是重点,它有5个参数,但是后四个都有默认的参数,但是还是解释一下它们的含义。
local_sap:类型是ACE_Addr的引用,不用说了吧,bind()函数的地址参数reuse_addr:这个参数表示是否打开SO_REUSEPORT这个选项,至于这个选项的含义很长的,这里给你一个链接:http://www.cnblogs.com/mydomain/archive/2011/08/23/2150567.html 讲的很详细。protocol_family:就是sock函数的第1个参数,地址族,默认就好backlog:这个是listen()函数的第二个参数,意义就不说了protocol:sock()函数的第3个参数,这个参数最好不要改,让系统自己确定使用的协议就好,当然默认是TCP
接下来是两个open()函数,这两个函数的参数分别对应两个构造函数,连参数都是一样的,实际上两个构造函数内部就是调用这两个自己对应的open()函数来完成的,当然如果你使用的无参构造函数,那么这个open()函数你还是仔细写一下。
/// Close the socket. Returns 0 on success and -1 on failure. int close (void);
关闭函数,很简单。
接下来就是两个accept()函数,也是重中之重,第二个不说了,因为它要就在windows中才有可能用到。
int accept (ACE_SOCK_Stream &new_stream, ACE_Addr *remote_addr = 0, ACE_Time_Value *timeout = 0, bool restart = true, bool reset_new_handle = false) const;
解释一下参数的意义:
new_stream:代表一个通信对象,服务器将通过这个对象与服务器来通信,简单的说,就是用这个对象来调用send,recv等函数来进行通信的remote_addr:请求连接的客户端的地址timeout:设置超时时间,0(NULL)就是阻塞模式,传入timeout(0,0)代表等待0s,也就是非阻塞模式(多好,连超时都设置好了)restart:这个参数代表党accept调用被某些原因中断后,会自动重启accept函数
最后一个参数很麻烦,最后一个参数,意味着很少的情况才会修改它,或者说不鼓励你去修改它,默认就好
在这个类中,其实就两个函数,一个open(),一个accept(),那么我们很容易能猜到,open()中完成了bind()和listen()调用,accept中完成了accept()函数的调用,那么到底是不是呢?
我们先来看一下open()函数的源代码:
intACE_SOCK_Acceptor::open (const ACE_Addr &local_sap, int reuse_addr, int protocol_family, int backlog, int protocol){ ACE_TRACE ("ACE_SOCK_Acceptor::open"); if (local_sap != ACE_Addr::sap_any) protocol_family = local_sap.get_type (); else if (protocol_family == PF_UNSPEC) {#if defined (ACE_HAS_IPV6) protocol_family = ACE::ipv6_enabled () ? PF_INET6 : PF_INET;#else protocol_family = PF_INET;#endif /* ACE_HAS_IPV6 */ } if (ACE_SOCK::open (SOCK_STREAM, protocol_family, protocol, reuse_addr) == -1) return -1; else return this->shared_open (local_sap, protocol_family, backlog);}
这里面最重要的就是最后的两个open()函数,前面的一些是确定地址族的判断,可以不用管(当然我用的是默认),我们来看第一个,也就是ACE_SOCK::open()函数,我们来看它的定义:
intACE_SOCK::open (int type, int protocol_family, int protocol, int reuse_addr){ ACE_TRACE ("ACE_SOCK::open"); int one = 1; this->set_handle (ACE_OS::socket (protocol_family, type, protocol)); if (this->get_handle () == ACE_INVALID_HANDLE) return -1; else if (protocol_family != PF_UNIX && reuse_addr && this->set_option (SOL_SOCKET, SO_REUSEADDR, &one, sizeof one) == -1) { this->close (); return -1; } return 0;}
我们可以看到两个我们很熟悉的函数名称,sock()和set_option(),第一个就是sock()函数的包裹函数了,第二个原型就是setsocketopt这个函数,也就是在这里我们设置了SO_REUSEPORT这个选项。
现在sock()函数找到了,还有两个三个函数,会在另外的open()函数中吗?
我们看下另外的一个open()函数的定义:(由于代码过长,我截取了其中的一部分,就是ipv6的那一部分,只看ipv4的):
intACE_SOCK_Acceptor::shared_open (const ACE_Addr &local_sap, int protocol_family, int backlog){ ACE_TRACE ("ACE_SOCK_Acceptor::shared_open"); int error = 0; if (protocol_family == PF_INET) { sockaddr_in local_inet_addr; ACE_OS::memset (reinterpret_cast<void *> (&local_inet_addr), 0, sizeof local_inet_addr); if (local_sap == ACE_Addr::sap_any) { local_inet_addr.sin_port = 0; } else local_inet_addr = *reinterpret_cast<sockaddr_in *> (local_sap.get_addr ()); if (local_inet_addr.sin_port == 0) { if (ACE::bind_port (this->get_handle (), ACE_NTOHL (ACE_UINT32 (local_inet_addr.sin_addr.s_addr))) == -1) error = 1; } else if (ACE_OS::bind (this->get_handle (), reinterpret_cast<sockaddr *> (&local_inet_addr), sizeof local_inet_addr) == -1) error = 1; } else if (ACE_OS::bind (this->get_handle (), (sockaddr *) local_sap.get_addr (), local_sap.get_size ()) == -1) error = 1; if (error != 0 || ACE_OS::listen (this->get_handle (), backlog) == -1) { ACE_Errno_Guard g (errno); // Preserve across close() below. error = 1; this->close (); } return error ? -1 : 0;}
listen()函数调用应该看的很清楚,但是bind()函数却有很多,我来就是一下这个条件语句:
if 需要bind的地址是个空的地址(就是ACE_INET_Addr是空) 将地址的端口号设为0else 将我们的非空地址的指针传进来if 这个if就省略不说了else 就执行我们期望的bind()函数
到现在为止。sock(),bind(),listen()全部都出来了,那么最后一个accept()调用当然就在我们类中的accept()函数中了,但是我们还是来看一下:
int
ACE_SOCK_Acceptor::accept (ACE_SOCK_Stream &new_stream,
ACE_Addr *remote_addr,
ACE_Time_Value *timeout,
bool restart,
bool reset_new_handle) const
{
ACE_TRACE (“ACE_SOCK_Acceptor::accept”);
int in_blocking_mode = 0; if (this->shared_accept_start (timeout, restart, in_blocking_mode) == -1) return -1; else { // On Win32 the third parameter to <accept> must be a NULL // pointer if we want to ignore the client's address. int *len_ptr = 0; sockaddr *addr = 0; int len = 0; if (remote_addr != 0) { len = remote_addr->get_size (); len_ptr = &len; addr = (sockaddr *) remote_addr->get_addr (); } do new_stream.set_handle (ACE_OS::accept (this->get_handle (), addr, len_ptr)); while (new_stream.get_handle () == ACE_INVALID_HANDLE && restart && errno == EINTR && timeout == 0); // Reset the size of the addr, so the proper UNIX/IPv4/IPv6 family // is known. if (new_stream.get_handle () != ACE_INVALID_HANDLE && remote_addr != 0) { remote_addr->set_size (len); if (addr) remote_addr->set_type (addr->sa_family); } } return this->shared_accept_finish (new_stream, in_blocking_mode, reset_new_handle);}
里面有三个accept函数,第一个shared_accept_start()函数,这个函数完成了定时功能,第二个accept()函数就是我们期望的,最后的那个函数,第三个shared_accept_finish()函数完成了将句柄(可以理解为文件表示符)与我们传进去的ACE_SOCK_Stream关联起来,完成通信。
ACE_SOCK_Acceptor真的是帮我们做了很多的工作,不需要我们直接操作复杂且难懂的OS的API,很强大的一个类。
希望对看完的你们有帮助。
- ACE中ACE_SOCK下ACE_SOCK_Acceptor类解析
- ACE_SOCK下的几个类
- ACE中UDP通信ACE_INET_Addr类ACE_SOCK_Acceptor类ACE_SOCK_Connector类ACE_SOCK_Stream
- ACE - ACE_INET_Addr, ACE_SOCK_Acceptor, ACE_SOCK_Connector, ACE_SOCK_Stream
- ACE_SOCK
- ACE基本APISOCKET编程TCPACE_INET_Addr类ACE_SOCK_Acceptor类ACE_SOCK_Connector类ACE_SOCK_Stream
- ACE学习之ACE_INET_Addr,ACE_SOCK_Acceptor 源代码
- 关于ACE静态库不能使用ACE_SOCK_Acceptor::accpet函数的迷思
- Linux下ACE、xml解析库开发环境搭建
- ACE命令参数解析
- Windows中ACE在MinGW下的安装
- ACE期货类ACE_Future返回异步调用结果原理解析
- linux下编译ACE
- Linux下安装ACE
- cygwin 下的 ace
- WINDOWS 下编译ace
- linux下 编译 ace
- Linux 下编译ACE
- html基础试题
- 如何查看电脑最全详细信息
- iOS小项目-使用Slider完成三种颜色的改变
- mina源码分析---4
- MFC程序引导过程(二)
- ACE中ACE_SOCK下ACE_SOCK_Acceptor类解析
- pthread_cond_signal虚假唤醒(spurious wakeup)
- MYSQL数据库乱码解决方案
- Linux gcc,gdb命令及vim配置
- Objective-C中对IPhone设备震动的调用
- python 基本知识学习
- JAVA 集合框架
- linux 命令及shell 知识小点汇集
- C++字符串格式化文章