PHP 与C++检索用户IP

发布于 2024-10-19 01:40:43 字数 1052 浏览 4 评论 0原文

我有一个 C++ 控制台应用程序,它使用 wininet.h 访问 URL,并下载网页的内容。

内容通常只是一个 IP 地址。它在这里: http://www.whatismyip.com/automation/n09230945.asp

一切都很好。

然后我决定用 PHP 创建自己的 IP 检查器,使用以下代码:

<?php

$ip = $_SERVER['REMOTE_ADDR'];

header("Cache-Control: private");
header("Content-Type: text/html");

echo $ip;

?>

这在浏览器中看起来是正确的,与 Whatismyip.com 的结果相同,但 C++ 程序只是在 IP 后面添加一堆垃圾,然后重复 IP 一半被切断,然后添加更多垃圾。

是什么原因造成的?我尝试分析标题,但无法发现差异。

另外,我尝试将一个纯 txt 文件放到服务器上,C++ 程序可以完美读取它。

我还尝试将标题更改为纯文本/文本和文本/纯文本。相同的结果。

感谢您的帮助!

编辑:这是 C++ 代码的一部分:

HINTERNET OpenAddress = InternetOpenUrl(connect,"http://www...", NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_KEEP_CONNECTION, 0);

char DataReceived[16] = " ";
DWORD NumberOfBytesRead = 0;
while (InternetReadFile(OpenAddress, DataReceived, 16, &NumberOfBytesRead) &&     NumberOfBytesRead)
{
     cout << DataReceived;
}

I have a C++ console app that uses wininet.h to go out to a URL, and download the contents of a web page.

The contents are usually just a single IP address. It goes here: http://www.whatismyip.com/automation/n09230945.asp

Everything works great.

Then I decided to create my own IP checker in PHP, using the following code:

<?php

$ip = $_SERVER['REMOTE_ADDR'];

header("Cache-Control: private");
header("Content-Type: text/html");

echo $ip;

?>

This looks correct in the browser, identical whatismyip.com's results, but the C++ program just adds bunch of junk after the IP, then repeats the IP half cut off, and then adds more junk.

What is causing this? I tried analyzing the headers, but I can't spot the difference.

Also, I tried putting a plain txt file on to the server, and the C++ program reads it perfect.

I also tried changing my headers to both plain/text and text/plain. Same result.

Thank you for your help!

Edit: Here's a portion of the C++ code:

HINTERNET OpenAddress = InternetOpenUrl(connect,"http://www...", NULL, 0, INTERNET_FLAG_PRAGMA_NOCACHE|INTERNET_FLAG_KEEP_CONNECTION, 0);

char DataReceived[16] = " ";
DWORD NumberOfBytesRead = 0;
while (InternetReadFile(OpenAddress, DataReceived, 16, &NumberOfBytesRead) &&     NumberOfBytesRead)
{
     cout << DataReceived;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

总攻大人 2024-10-26 01:40:43

cout 将期望字符串以 null 结尾。因为您只是将字节读入缓冲区,而不是在最后以空终止它们,所以 cout 将继续执行您已读取的字节末尾,并继续转储内存,直到它遇到空指针或内存保护启动。

根据您的代码,猜测发生的情况是这样的:

  1. 您分配了一个 16 字节的内存区域。
  2. 您调用 InternetReadFile。这会将 IP 地址(例如“127.0.0.1”)放入缓冲区中,不带空终止符。
  3. 您可以使用 DataReceived 调用 cout。这是一个 char 数组,因此 cout 期望它是一个以 null 结尾的字符串。它输出从缓冲区开头到“127.0.01”之后的每个字符,直到在内存中找到 0。
  4. 因为“127.0.0.1”是所有要读取的内容,并且您的缓冲区比该值更大,所以对 InternetReadFile 的下一次调用会将 NumberOfBytesRead 保留为零,因此您的循环仅发生一次。

InternetReadFile() 一无所知,但我猜想,如果您只抓取其中包含 IP 地址的单行,这样的方法应该可行:

char DataReceived[64]; // I guess I'm antsy about having plenty of room

DWORD NumberOfBytesRead = 0;
if (InternetReadFile(OpenAddress, DataReceived, 63, &NumberOfBytesRead)) {
  DataReceived[NumberOfBytesRead] = '\0';
  cout << DataReceived;
} else // handle error condition

但从根本上来说,我认为你遇到的主要问题是混淆了一个只是一堆字节的缓冲区和一个友好的空终止字符串,你应该理解这一点,并且也许寻找一些使用 InternetReadFile 的现有示例,看看它们是如何使用的工作,以及你需要做什么。

cout will expect a string to be null-terminated. Because you're just reading bytes into a buffer, and not null-terminating them at the end, cout will carry on past the end of the bytes you've read and just carry on dumping memory out until it hits a null pointer or memory protection kicks in.

With your code, what's happening is this, at a guess:

  1. You assign a 16-byte area of memory.
  2. You call InternetReadFile. This puts an IP address, say "127.0.0.1" in your buffer, without a null terminator.
  3. You call cout with DataReceived. This is a char array, and cout therefore expects it to be a null-terminated string. It outputs every character from the start of the buffer, right past "127.0.01" and onwards until it finds a 0 in memory.
  4. Because "127.0.0.1" was all there is to read, and your buffer was bigger than that, the next call to InternetReadFile leaves NumberOfBytesRead as zero, so your loop only happens once.

Don't know anything about InternetReadFile(), but I'd guess an approach like this should work if you're only grabbing a single line with an IP address in it:

char DataReceived[64]; // I guess I'm antsy about having plenty of room

DWORD NumberOfBytesRead = 0;
if (InternetReadFile(OpenAddress, DataReceived, 63, &NumberOfBytesRead)) {
  DataReceived[NumberOfBytesRead] = '\0';
  cout << DataReceived;
} else // handle error condition

But fundamentally, I think the main problem you're having is in confusing a buffer that's just a bunch of bytes with a nice friendly null-terminated string, and you should understand that, and maybe look for some existing examples of using InternetReadFile with that in mind to see how they work, and therefore what you need to do.

土豪 2024-10-26 01:40:43
<?PHP
$ip = $_SERVER['REMOTE_ADDR']; //Checks internet remote adderater,
$fh = "YourSecretFileHere.txt"; //Starts a socket in w_temppTXT, aka the .txt
fwrite($fh, 'IP Address:'.'$ip'); //Writes Info From IP into File, 
fclose($fh); //Closes file, ends writing boot comp.
if $fh = ""; { //If the file is empty,
echo "IP File Is Empty!"; //Echo's From Above ^
else {
echo ""; //Prints nothing from variables
     }
?>
<?PHP
$ip = $_SERVER['REMOTE_ADDR']; //Checks internet remote adderater,
$fh = "YourSecretFileHere.txt"; //Starts a socket in w_temppTXT, aka the .txt
fwrite($fh, 'IP Address:'.'$ip'); //Writes Info From IP into File, 
fclose($fh); //Closes file, ends writing boot comp.
if $fh = ""; { //If the file is empty,
echo "IP File Is Empty!"; //Echo's From Above ^
else {
echo ""; //Prints nothing from variables
     }
?>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文