nginx模塊編程之獲取客戶ip及端口號


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);//大小端轉換

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM