如何在apache中获得客户端的端口?

如何在apache中获得客户端的端口号?

正如题,在apache服务器如何获取来访者的端口号。

正解:apr_port_t port = r->connection->remote_addr->port;

据我所知,apache暂不提供这种功能,但是居然客户端和服务器端要通过网络连接肯定是能得到源端ip地址和端口号。

下面来看看怎么获得客户端端口号。

首先查看apache模块要处理的request_rec、conn_rec、apr_sockaddr_t这些数据结构。

 

struct apr_sockaddr_t {
    /** The pool to use... */
    apr_pool_t *pool;
    /** The hostname */
    char *hostname;
    /** Either a string of the port number or the service name for the port */
    char *servname;
    /** The numeric port */
   <span style="color: #993300;"> apr_port_t port;</span>
    /** The family */
    apr_int32_t family;
    /** How big is the sockaddr we're using? */
    apr_socklen_t salen;
    /** How big is the ip address structure we're using? */
    int ipaddr_len;
    /** How big should the address buffer be?  16 for v4 or 46 for v6
     *  used in inet_ntop... */
    int addr_str_len;
    /** This points to the IP address structure within the appropriate
     *  sockaddr structure.  */
    void *ipaddr_ptr;
    /** If multiple addresses were found by apr_sockaddr_info_get(), this 
     *  points to a representation of the next address. */
    apr_sockaddr_t *next;
    /** Union of either IPv4 or IPv6 sockaddr. */
    union {
        /** IPv4 sockaddr structure */
        struct sockaddr_in sin;
#if APR_HAVE_IPV6
        /** IPv6 sockaddr structure */
        struct sockaddr_in6 sin6;
#endif
#if APR_HAVE_SA_STORAGE
        /** Placeholder to ensure that the size of this union is not
         * dependent on whether APR_HAVE_IPV6 is defined. */
        struct sockaddr_storage sas;
#endif
    } sa;
};

从这里可以看出,port字段是远程客户端的端口号,所以我们这里只要获得这个结构体就可以得到客户端的端口号。

那么这个结构体是怎么得到的呢?

conn_rec结构体里有个指针指向这里,

 

struct conn_rec {
    /** Pool associated with this connection */
    apr_pool_t *pool;
    /** Physical vhost this conn came in on */
    server_rec *base_server;
    /** used by http_vhost.c */
    void *vhost_lookup_data;

    /* Information about the connection itself */
    /** local address */
    apr_sockaddr_t *local_addr;
    /** remote address */
   <span style="color: #993300;"> apr_sockaddr_t *remote_addr;
       char *remote_ip;
</span>

这个conn_rec结构体又是通过request_rec得到。

 

struct request_rec {
    /** The pool associated with the request */
    apr_pool_t *pool;
    /** The connection to the client */
    conn_rec *connection;
    /** The virtual host for this request */
    server_rec *server;

最终获得途径是apr_port_t port = r->connection->remote_addr->port;

好了,问题解决了。

顺便附上apache LogFormat,从官方文档可以看出日志里是不能留客户端的端口的。

http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#formats

 

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>