nginx模块编程之获取客户ip及端口号
2015-08-18 16:13
537 查看
ngx_request_t结构体中有一个connection定义,该定义指向一个ngx_connection_t的结构体:
结构体定义如下:
结构体中,有两个sockaddr地址结构定义,分别是sockaddr以及local_sockaddr;前者为客户端地址,后者为服务器端地址;下面来看sockaddr的定义:
说明:
sa_family是地址家族,是“AF_xxx”的形式。常设为“AF_INET”,代表Internet(TCP/IP)地址族。
sa_data是协议地址,由sa_family决定。如果sa_family=AF_INET,则sa_data就是sockaddr_in的
sin_addr和sin_port,用于为套接口储存目标地址和端口信息。为了解决struct
sockaddr赋值以及访问,提供了了一个并列的结构struct sockadd_in(“in”代表
“Internet”),换句话说,sockaddr的数据存储大小和结构完全和sockaddr_in一致,可以直接强制转换。
关于这两个结构体,他们占用的内存大小是一样的,当sockaddr_in.sin_family = AF_INET时,他们的内存布局也一样的!看看sockaddr结构体自身就知道了,它仅仅是个char数组,大小与sockaddr_in等同。
这两个结构体使用转化的例子如下:
sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数
sockaddr结构强制转换成sockaddr_in结构,从而得到ip地址和端口号
结构体定义如下:
struct ngx_connection_s { void *data; ngx_event_t *read; ngx_event_t *write; ngx_socket_t fd; ngx_recv_pt recv; ngx_send_pt send; ngx_recv_chain_pt recv_chain; ngx_send_chain_pt send_chain; ngx_listening_t *listening; off_t sent; ngx_log_t *log; ngx_pool_t *pool; struct sockaddr *sockaddr; socklen_t socklen; ngx_str_t addr_text; ngx_str_t proxy_protocol_addr; #if (NGX_SSL) ngx_ssl_connection_t *ssl; #endif struct sockaddr *local_sockaddr; socklen_t local_socklen; ngx_buf_t *buffer; ngx_queue_t queue; ngx_atomic_uint_t number; ngx_uint_t requests; unsigned buffered:8; unsigned log_error:3; /* ngx_connection_log_error_e */ unsigned unexpected_eof:1; unsigned timedout:1; unsigned error:1; unsigned destroyed:1; unsigned idle:1; unsigned reusable:1; unsigned close:1; unsigned sendfile:1; unsigned sndlowat:1; unsigned tcp_nodelay:2; /* ngx_connection_tcp_nodelay_e */ unsigned tcp_nopush:2; /* ngx_connection_tcp_nopush_e */ unsigned need_last_buf:1; #if (NGX_HAVE_IOCP) unsigned accept_context_updated:1; #endif #if (NGX_HAVE_AIO_SENDFILE) unsigned busy_count:2; #endif #if (NGX_THREADS) ngx_thread_task_t *sendfile_task; #endif };
结构体中,有两个sockaddr地址结构定义,分别是sockaddr以及local_sockaddr;前者为客户端地址,后者为服务器端地址;下面来看sockaddr的定义:
struct sockaddr { unsigned short sa_family; /* address family, AF_xxx */ char sa_data[14]; /* 14 bytes of protocol address */ };
说明:
sa_family是地址家族,是“AF_xxx”的形式。常设为“AF_INET”,代表Internet(TCP/IP)地址族。
sa_data是协议地址,由sa_family决定。如果sa_family=AF_INET,则sa_data就是sockaddr_in的
sin_addr和sin_port,用于为套接口储存目标地址和端口信息。为了解决struct
sockaddr赋值以及访问,提供了了一个并列的结构struct sockadd_in(“in”代表
“Internet”),换句话说,sockaddr的数据存储大小和结构完全和sockaddr_in一致,可以直接强制转换。
struct sockaddr_in{ short int sin_family; /*地址族信息,通常是AF-xxxx的形式*/ unsigned short int sin_port; /*端口信息*/ struct in_addr sin_addr; /*网络地址*/ unsigned char sin_zero[8]; /*补位用的0,to make same size as struct sockaddr*/ }
关于这两个结构体,他们占用的内存大小是一样的,当sockaddr_in.sin_family = AF_INET时,他们的内存布局也一样的!看看sockaddr结构体自身就知道了,它仅仅是个char数组,大小与sockaddr_in等同。
这两个结构体使用转化的例子如下:
sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数
/*sockaddr_in强制转化为sockaddr,用于传入系统调用函数*/ int sockfd; struct sockaddr_in my_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); my_addr.sin_family = AF_INET; /* 主机字节序 */ my_addr.sin_port = htons(MYPORT); /* short, 网络字节序 */ my_addr.sin_addr.s_addr = inet_addr("192.168.0.1"); bzero(&(my_addr.sin_zero), 8); /* zero the rest of the struct */ //memset(&my_addr.sin_zero, 0, 8); bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));//将sockaddr_in强制转化为sockaddr,用于传入系统调用函数
sockaddr结构强制转换成sockaddr_in结构,从而得到ip地址和端口号
struct sockaddr_in *ip = (struct sockaddr_in *) (r->connection->sockaddr); char* addr = inet_ntoa(ip->sin_addr);//地址转化函数,返回字符串指针 unsigned short port = ntohs(ip->sin_port);//大小端转换
相关文章推荐
- nginx 常用全局变量
- 部署nginx前端优化模块ngx_pagespeed
- Keepalived+Nginx提供前端负载均衡+主从双机热备+自动切换
- NGINX location 在配置中的优先级
- 用 consul + consul-template + registrator + nginx 打造真正可动态扩展的服务架构
- nginx 配置错误页面
- nginx upstream作为变量
- CentOS6.x安装配置nginx
- Nginx 的日志压缩处理
- nginx配置长连接
- Nginx服务器上安装并配置PHPMyAdmin的教程
- 安装Nginx
- 在虚拟机中配置FastDFS+Nginx模块
- 使用virtualenv, uwsgi, nginx来布署flask
- nginx基础应用
- nginx 配置禁止访问目录或文件
- nginx部署
- nginx搭建tcp代理服务器
- Nginx服务器中的GZip配置参数详解
- nginx线程池源码分析