ngx_request_t结构体中有一个connection定义,该定义指向一个ngx_connection_t的结构体:
结构体定义如下:
1 struct ngx_connection_s { 2 void *data; 3 ngx_event_t *read; 4 ngx_event_t *write; 5 6 ngx_socket_t fd; 7 8 ngx_recv_pt recv; 9 ngx_send_pt send; 10 ngx_recv_chain_pt recv_chain; 11 ngx_send_chain_pt send_chain; 12 13 ngx_listening_t *listening; 14 15 off_t sent; 16 17 ngx_log_t *log; 18 19 ngx_pool_t *pool; 20 21 struct sockaddr *sockaddr; 22 socklen_t socklen; 23 ngx_str_t addr_text; 24 25 ngx_str_t proxy_protocol_addr; 26 27 #if (NGX_SSL) 28 ngx_ssl_connection_t *ssl; 29 #endif 30 31 struct sockaddr *local_sockaddr; 32 socklen_t local_socklen; 33 34 ngx_buf_t *buffer; 35 36 ngx_queue_t queue; 37 38 ngx_atomic_uint_t number; 39 40 ngx_uint_t requests; 41 42 unsigned buffered:8; 43 44 unsigned log_error:3; /* ngx_connection_log_error_e */ 45 46 unsigned unexpected_eof:1; 47 unsigned timedout:1; 48 unsigned error:1; 49 unsigned destroyed:1; 50 51 unsigned idle:1; 52 unsigned reusable:1; 53 unsigned close:1; 54 55 unsigned sendfile:1; 56 unsigned sndlowat:1; 57 unsigned tcp_nodelay:2; /* ngx_connection_tcp_nodelay_e */ 58 unsigned tcp_nopush:2; /* ngx_connection_tcp_nopush_e */ 59 60 unsigned need_last_buf:1; 61 62 #if (NGX_HAVE_IOCP) 63 unsigned accept_context_updated:1; 64 #endif 65 66 #if (NGX_HAVE_AIO_SENDFILE) 67 unsigned busy_count:2; 68 #endif 69 70 #if (NGX_THREADS) 71 ngx_thread_task_t *sendfile_task; 72 #endif 73 };
结构体中,有两个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);//大小端转换
时间: 2024-10-13 09:40:18