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);//大小端转换
时间: 2024-10-13 09:40:18

nginx模块编程之获取客户ip及端口号的相关文章

从HTTP请求中获取客户IP地址

/**     * 从HTTP请求中获取客户IP地址     *     * @param request http请求     * @return 客户IP地址     */    public static String getIPAddress( HttpServletRequest request )    {        String ip = request.getHeader( "x-forwarded-for" );        if ( ip == null ||

.Net Core/Framework之Nginx反向代理后获取客户端IP等数据探索

原文:.Net Core/Framework之Nginx反向代理后获取客户端IP等数据探索 公司项目最近出现获取访问域名.端口.IP错误现象,通过排查发现, 之前项目一直通过Nginx自定义Headers信息来获取,但最近运维人员失误操作造成自定义Header信息丢失,造成项目拿不到对应的数据.思前想后,想找找官方有没有关于此类问题通用标准化的解决方案. 一.Nginx配置如下: proxy_redirect off; proxy_set_header Host $host; proxy_set

linux socket通讯如何获取本地的源端口号

关于TCP IP网络通讯的资料非常多,TCP IP通过IP数据包模式进行端对端通讯.典型的TCP数据包如下 可以看到数据包包含了源端口号和目的端口号,客户端socket向服务端发起连接时,系统会给socket随机分配一个源端口号,我们可以通过getsocketname来获取连接成功的socket的原端口信息. 函数原型 [cpp] view plain copy #include <sys/socket.h> int getsockname(int sockfd, struct sockadd

nginx反向代理如何获取真实IP?

由于客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址. 1.安装--with-http_realip_module要想在程序中取得真实的IP,需对nginx重新编译,新增--with-http_realip_module选项,操作如下: cd /home/xxx/dev/nginx-1.10.2/ ./configure --with-http_realip_module make make ins

django获取客户ip

1 def get_client_ip(request): 2 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR') 3 if x_forwarded_for: 4 ip = x_forwarded_for.split(',')[-1].strip() 5 else: 6 ip = request.META.get('REMOTE_ADDR') 7 return ip 使用django来获取用户访问的IP地址 request.MET

webpack 配置IP 和端口号

最近在用webpack搭建本地服务器的时候,因为不想总是用localhost来跑,所以对webpack.config.js进行了配置,如下 devServer: { //publicPath: '/dist/', host: '192.168.0.104', inline: true, port: 8090, colors: true }, 打开如下图:

C#服务器获取客户端IP地址以及归属地探秘

背景:博主本是一位Windows桌面应用程序开发工程师,对网络通信一知半解.一日老婆逛完某宝,问:"为什么他们知道我的地址呢,他们是怎么获取我的地址的呢?" 顺着这个问题我们的探秘开始: 第一步:简单的服务搭建 思路,通过HttpListener在本地搭建一个简易的服务器,开发程序为控制台接口,核心类 HttpListenerService: 方法 Start()开启线程池针对指定IP进行监听,本地的端口选取的9527(周星驰唐伯虎点秋香在华府的编号)  public void Sta

iOS获取本地ip(基本通用)

今天有个朋友问我怎样訪问手机ip,上网找了几个,用了近200多行代码,最后发现头文件用的居然还是Linux中的,OC没有这个头文件.感觉socket本身应该能够后去自己的ip就试了一下,果然7.8行代码就攻克了.这个基本是c的socket,差点儿通用,别的平台也能够使用. - (NSString *)getLocalIP{ struct sockaddr_in sa; socklen_t len = sizeof(sa); if(getsockname(sockfd, (struct socka

nginx模块开发获取post参数

> 您好!>     我想请问下nginx模块里面怎么获取post参数,能有具体的代码更好!谢谢> 对于 "application/x-www-form-urlencoded" 格式的 POST 参数获取,可以参考 ngx_lua 模块的ngx.req.get_post_args() 函数以及 ngx_form_input 模块的实现: http://wiki.nginx.org/HttpLuaModule#ngx.req.get_post_args https://