为啥获取客户端ip地址总是:204.204.204.204

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为啥获取客户端ip地址总是:204.204.204.204相关的知识,希望对你有一定的参考价值。

源码如下:
// 版本:1.0
// 日期:2013.7.13
// 更改日期:
// 功能:基于TCP的Sockets编程

// Win32Sock_service.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <WinSock2.h> //包含头文件
#include <stdio.h>
#include <Windows.h>
#pragma comment(lib, "WS2_32.lib") //显式连接套接字库

int _tmain(int argc, _TCHAR* argv[])

WSADATA data; //定义WSADATA结构体对象
WORD w = MAKEWORD(2,0); //定义版本号码
char sztext[] = "welcome !!\r\n"; //定义并初始化化发送到客户端的字符串数组
::WSAStartup(w, &data); //初始化套接字库
SOCKET s = NULL,s1 = NULL; //定义连接套接字和数据收发套接字句柄
s = ::socket(AF_INET, SOCK_STREAM, 0); //创建TCP套接字
sockaddr_in addr,addr2; //定义套接字地址结构
int n =sizeof(addr2); //获取套接字地址结构大小
addr.sin_family = AF_INET; //初始化地址结构
addr.sin_port = htons(1065);
addr.sin_addr.S_un.S_addr = INADDR_ANY;
::bind(s, (sockaddr*)&addr2,sizeof(addr)); //绑定套接字
::listen(s, 5); //监听套接字
printf("service is running\r\n");
while(true)

s1 = ::accept(s, (sockaddr*)&addr2, &n); //接受连接请求
if (s1 != NULL)

printf("%s have been connect now", inet_ntoa(addr2.sin_addr));
::send(s1,sztext, sizeof(sztext), 0); //向客户端发送字符串数组
//定义
::closesocket(s); //关闭套接字句柄
::closesocket(s1);
::WSACleanup(); //释放套接字库
if (getchar())

return 0;
else
::Sleep(100);




204换成16进制是0xcc,我记得这是vc初始化堆栈的时候使用的数据
也就是说你accept没有成功,所以里面没数据。

我知道你进行了出错判断,判断accept有没有成功。但是很可惜,accept失败的时候并不是返回NULL
它返回的是 (SOCKET) -1 (或者写 ~0 也一样)
参考技术A

获取地址可以通过getsockname()函数和getpeername()函数来分别获得调用bind()和connect()后套接字的主机地址和端口号和远端端点地址和端口号。我在使用getpeername时第三个参数没有初始化于是就出现了204.204.204.204。应该是inet_ntop和inet_ntoa在没有数据的情况下给的数吧,参考空雪梦见的回答

参考技术B “bind(s, (sockaddr*)&addr2,sizeof(addr));” 改为“bind(s, (sockaddr*)&addr,sizeof(addr));”即可 。 参考技术C 传说中的烫烫烫

如何在 servlet 中获取客户端的远程地址?

【中文标题】如何在 servlet 中获取客户端的远程地址?【英文标题】:How do I get the remote address of a client in servlet? 【发布时间】:2011-06-08 09:44:33 【问题描述】:

有什么方法可以让客户端的原始 IP 地址进入服务器? 我可以使用request.getRemoteAddr(),但我似乎总是获得代理或网络服务器的IP。

我想知道客户端用来连接我的 IP 地址。反正我能得到它吗?

【问题讨论】:

【参考方案1】:

试试这个:

public static String getClientIpAddr(HttpServletRequest request)   
        String ip = request.getHeader("X-Forwarded-For");  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))   
            ip = request.getHeader("Proxy-Client-IP");  
          
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))   
            ip = request.getHeader("WL-Proxy-Client-IP");  
          
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))   
            ip = request.getHeader("HTTP_CLIENT_IP");  
          
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))   
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
          
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))   
            ip = request.getRemoteAddr();  
          
        return ip;  
      

【讨论】:

可以吗,这种情况下,用if conditiona代替if/else? 是的,因为我们需要检查之前的操作是否成功,也许使用do-while会更好 X-Forwarded-For 可以包含多个 IP 地址。【参考方案2】:

request.getRemoteAddr() 就是这样。您的代理似乎更改了源 IP。当一些代理这样做时,他们会在一些自定义 http 标头中添加原始 IP。使用request.getHeaderNames()request.getHeaders(name) 并打印所有这些以查看是否有任何感兴趣的内容。喜欢X-CLIENT-IP(做了一个,但它们看起来像这样)

【讨论】:

谢谢,我会检查标题....尽管例如当它通过网络服务器时,我会得到网络服务器地址 你的意思是 request.getHeaderNames() 吗?【参考方案3】:

由于这通常是部署问题,而不是应用程序问题,另一种方法是适当地配置应用程序容器。配置完成后,容器会负责检查相应的标头,并且您的应用程序会继续使用 request.getRemoteAddr()

例如,在 Tomcat 中,您可以使用 Remote IP Valve。我会假设大多数应用服务器都有类似的功能。

容器还可以负责了解您的前端负载平衡器是否正在终止 SSL 连接,并通过 HTTP 将请求转发到应用服务器。当您的应用程序需要为其自身生成 URL 时,这一点很重要。

【讨论】:

【参考方案4】:

我用过的最好的解决方案

public String getIpAddr(HttpServletRequest request)       
   String ip = request.getHeader("x-forwarded-for");      
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))       
       ip = request.getHeader("Proxy-Client-IP");      
         
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))       
       ip = request.getHeader("WL-Proxy-Client-IP");      
         
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))       
       ip = request.getRemoteAddr();      
         
   return ip;      
 

【讨论】:

【参考方案5】:

为什么不使用这样更优雅的解决方案?

private static final List<String> IP_HEADERS = Arrays.asList("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");

public static String getClientIpAddr(HttpServletRequest request) 
    return IP_HEADERS.stream()
        .map(request::getHeader)
        .filter(Objects::nonNull)
        .filter(ip -> !ip.isEmpty() && !ip.equalsIgnoreCase("unknown"))
        .findFirst()
        .orElseGet(request::getRemoteAddr);

对您的代码进行重复数据删除!

【讨论】:

【参考方案6】:

你不能以有意义的方式做到这一点。

代理可能会或可能不会添加代理标头,但在许多情况下,无论如何这将是一个仅限内部的地址,因此对您来说毫无意义。无论如何,组织边缘的大多数代理都被配置为尽可能少地透露网络内部信息。

您打算将这些信息用于什么目的?

【讨论】:

好吧,我有点需要记录正在访问的用户的地址。你是对的,一些代理似乎删除了它,我经常让代理替换它....我在想我是否可以从 SSL 会话中获取一些信息【参考方案7】:

“x-forwarded-for”请求标头包含原始客户端 IP(如果使用代理或负载平衡器)。但我认为并非所有代理/磅都添加此标头。

这里有一些java代码来解析头部: http://www.codereye.com/2010/01/get-real-ip-from-request-in-java.html

如果此标头不存在,那么我将按照@Bozho 的建议继续

【讨论】:

【参考方案8】:
String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null) 
            ipAddress = request.getHeader("X_FORWARDED_FOR");
            if (ipAddress == null)
                ipAddress = request.getRemoteAddr();
            
        

【讨论】:

【参考方案9】:

为什么我认为我们应该首先尝试从标头“X-Forwarded-For”获取 IP?如果您来自request.getRemoteAddr(),则可能是client's real ip or last proxy's ip which forwards the request。因此我们无法判断它属于哪个条件。但是,如果 'X-Forwarded-For' 被设置到标头中,则客户端 ip 必然是您从中获得的最左边的部分。

    /**
     * Try to get real ip from request:
     * <ul>
     *     <li>try X-Forwarded-For</li>
     *     <li>try remote address</li>
     * </ul>
     *
     * @param request    request
     * @return real ip or ""
     */
    private String tryGetRealIp(HttpServletRequest request) 
        // X-Forwarded-For: <client>, <proxy1>, <proxy2>
        // If a request goes through multiple proxies, the IP addresses of each successive proxy is listed.
        // This means, the right-most IP address is the IP address of the most recent proxy and
        // the left-most IP address is the IP address of the originating client.
        String forwards = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotBlank(forwards)) 
            // The left-most IP must be client ip
            String ip = StringUtils.substringBefore(forwards, ",");
            return ip;
         else if (StringUtils.isNotBlank(request.getRemoteAddr())) 
            // this could be real client ip or last proxy ip which forwards the request
            return request.getRemoteAddr();
        
        return "";
    

【讨论】:

【参考方案10】:

request.getHeader("True-Client-IP")

它将返回客户端IP地址

【讨论】:

【参考方案11】:
InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();

【讨论】:

这只是给出本地主机的IP。

以上是关于为啥获取客户端ip地址总是:204.204.204.204的主要内容,如果未能解决你的问题,请参考以下文章

为啥空 IP 地址将计算机名称解析为 204.204.204.204?

为什么空IP地址将计算机名称解析为204.204.204.204?

为什么我会以这种背景颜色(rgb(204,204,204)无重复滚动0%0%/自动填充框边框框)格式?

blog主题——黑夜

Linux top 使用技巧

echarts 各项 参数