PDA

View Full Version : سوال: این برنامه رو چطوری compile کنم !؟



SajadT2010
شنبه 09 اسفند 1393, 22:20 عصر
سلام.
دوستان من یک برنامه نوشتم که یک سری آیپی و مشخصات رو از یک فایل میخونه و با فانکشن system میاد دستور ping اجرا میکنه و نتیجه رو میریزه توی یک فایل و بعد دوباره اون فایل باز میشه و تجزیه تحلیل میشه و اطلاعات لازم رو برمیداره میریزه توی یک فایل دیگه و من از اون فایل استفاده میکنم !!!!
عملا کلی لقمه دور سر چرخیده میشه و از طرفی چون دائم فایل‌ها رو باز میکنه و میخونه و مینویسه برنامه میره توی کما و هنگ میکنه !!! (حدود ۲۰۰۰ ایپی لوکال داخل شبکه رو باید پینگ بگیره)
البته چون من تخصص اصلیم C++‎‎‎‎‎‎ نیست اینجوری نوشتم در حدی که کارم راه بیفته !!!
الان میخوام برنامه رو با icmp بنویسم که بتونم ازش مستقیم اعداد مورد نظرم رو بگیرم و اینقدر لازم نباشه با فایل‌ها کار کنم. این کد رو پیدا کردم که خیلی به چیزی که میخوام نزدیک هست. اما هیچ جوری نتونستم کامپایلش کنم. اول که به هدرها گیر میداد و دونه به دونه هدرها رو پیدا کردم بعد هم به کامپایلر گیر داد که از نسخه های GNU استفاده کن. من با borland C++‎‎‎‎‎‎ کار میکنم و visual studio هم خیلی با محیطش آشنا نیستم.
(تو این انجمن هم گشت و گذار زدم چیزی که میخواستم پیدا نکردم)
چطوری این رو کامپایل کنم و خروجی بگیرم ؟






//Additional Dependencies: Ws2_32.lib, Iphlpapi.lib
//Additional Include Directories: ..PlatformSDK\Misc\Icmp

#include "stdafx.h"
#include "windows.h"
#include "conio.h"
#include "Iphlpapi.h"
#include "Icmpapi.h"
using namespace std;

void ping(char *destination);

int _tmain(int argc, _TCHAR* argv[])
{
ping("advisor.com");
ping("universalthread.com");
ping("west-wind.com");

cout << "\nPress any key...";
getch();
return 0;
}

void ping(char *destination)
{
WSADATA wsaData;
WSAStartup(0x0202, &wsaData);

hostent* remoteHost;
remoteHost = gethostbyname(destination);
if (WSAGetLastError() != 0)
{
cout << "Ping request could not find host "
<< destination
<< ". Please check the name and try again.\n" << endl;
WSACleanup();
return;
}

HANDLE hIcmpFile = IcmpCreateFile();
if (hIcmpFile==INVALID_HANDLE_VALUE)
{
cout << "IcmpCreateFile failed with error code: "
<< GetLastError() << endl;
WSACleanup();
return;
}

IPAddr* ipaddr = reinterpret_cast< IPAddr* >
(remoteHost->h_addr_list[0]);

cout << "Pinging " << destination << " ["
<< inet_ntoa(*reinterpret_cast< in_addr* >(ipaddr))
<< "]\n" << endl;

LPVOID ReplyBuffer = (VOID*) malloc(sizeof(ICMP_ECHO_REPLY));

for (int i=0; i<3; i++)
{
if (IcmpSendEcho(hIcmpFile, *ipaddr,
0,0,NULL, ReplyBuffer,sizeof(ICMP_ECHO_REPLY),1000)==0)
{
cout << "IcmpSendEcho failed with error code: "
<< GetLastError() << endl;
}
else
{
PICMP_ECHO_REPLY pEchoReply = (PICMP_ECHO_REPLY)ReplyBuffer;
in_addr ipreplied;
ipreplied.S_un.S_addr=pEchoReply->Address;

cout << "Reply from " << inet_ntoa(ipreplied)
<< ": bytes=" << pEchoReply->DataSize
<< " time=" << pEchoReply->RoundTripTime << "ms" << endl;
}
Sleep(500);
}

cout << endl;
free(ReplyBuffer);
IcmpCloseHandle(hIcmpFile);
WSACleanup();
}

rahnema1
شنبه 09 اسفند 1393, 23:31 عصر
سلام یک نسخه از برنامه codeblocks را دانلود کنید تا باهش کامپایل کنید
داخل فایل زیپ فایل باپسوند cbp را باز کرده و از منوی مربوطه گزینه compile را بزنید
http://www.sharefile.ir/uploads/1425211302.zip

SajadT2010
یک شنبه 10 اسفند 1393, 09:45 صبح
سلام. خیلی ممنون.
در حال حاضر این ارور رو میگیرم.



||=== Build: Release in ping (compiler: GNU GCC Compiler) ===|
obj\Release\main.o:main.cpp|| undefined reference to `IcmpCreateFile@0'|
obj\Release\main.o:main.cpp|| undefined reference to `IcmpSendEcho@32'|
obj\Release\main.o:main.cpp|| undefined reference to `IcmpCloseHandle@4'|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 2 second(s)) ===|


خودم شرچ کردم، فکر میکنم از فایلی به اسم iphlpapi.lib هم توی برنامه استفاده کنم اما نمیدونم چطوری !
این دستور هم جواب نداد



#pragma comment(lib, "IPHLPAPI.lib")


محتوای فایل icmpapi.h که include کردم هم این هست (خود کامپایلر نداشت من دانلود کردم)





/*
* Interface to the ICMP functions.
*
* Copyright (C) 1999 Francois Gouget
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/


#ifndef __WINE_ICMPAPI_H
#define __WINE_ICMPAPI_H


#ifdef __cplusplus
extern "C" {
#endif




HANDLE WINAPI IcmpCreateFile(
VOID
);


BOOL WINAPI IcmpCloseHandle(
HANDLE IcmpHandle
);


DWORD WINAPI IcmpSendEcho(
HANDLE IcmpHandle,
IPAddr DestinationAddress,
LPVOID RequestData,
WORD RequestSize,
PIP_OPTION_INFORMATION RequestOptions,
LPVOID ReplyBuffer,
DWORD ReplySize,
DWORD Timeout
);




#ifdef __cplusplus
}
#endif


#endif /* __WINE_ICMPAPI_H */

rahnema1
یک شنبه 10 اسفند 1393, 10:23 صبح
ظاهرا این نسخه موجود در coeblocks این هدر ها را نداره که لازمه از mingw-w64 استفاده کنید که باید دانلود کنید و تنظیمات codeblocks را تغییر بدید
فکر کنم همون بهتره که با visual studio کار کنید
در ابتدای فایل main این دو خط را اضافه کنید

#pragma comment(lib, "IPHLPAPI.lib")
#pragma comment(lib, "ws2_32.lib")

و در ویژوال استادیو یک پروژه به صورت به صورت console application درست کنید و کامپایل کنید نحوه ایجاد console application اینجا گفته شده:
https://msdn.microsoft.com/en-us/library/ms235629.aspx

SajadT2010
یک شنبه 10 اسفند 1393, 11:05 صبح
باز هم خطا داد.
اول که به فانکشن getch گیر داد که تو فایل conio.h مشکل داره که من جایگزین کردم با cin و مساله حل شد.
و اما خطای فعلی:



1>------ Build started: Project: Sajad, Configuration: Debug Win32 ------
1>Build started 3/1/2015 11:44:01 AM.
1>InitializeBuildStatus:
1> Touching "Debug\Sajad.unsuccessfulbuild".
1>ClCompile:
1> main.cpp
1>ManifestResourceCompile:
1> All outputs are up-to-date.
1>LINK : fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:10.45
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

SajadT2010
یک شنبه 10 اسفند 1393, 11:06 صبح
نسخه visual studio هم ۲۰۱۰ هست

rahnema1
یک شنبه 10 اسفند 1393, 11:40 صبح
نسخه visual studio هم ۲۰۱۰ هست

در سایت زیر نحوه بر طرف کردن خطای مذکور بحث شده اگه جواب نگرفتید تا از همون mingw-w64 استفاده کنیم
http://stackoverflow.com/questions/10888391/error-link-fatal-error-lnk1123-failure-during-conversion-to-coff-file-inval

SajadT2010
یک شنبه 10 اسفند 1393, 12:04 عصر
مرسی از راهنمایی و حوصله شما. با انجام این مرحله مشکل حل شد و برنامه اجرا شد:



Project Properties


-> Configuration Properties
-> Linker (General)
-> Enable Incremental Linking -> "No (/INCREMENTAL:NO)"



دو تا چیزی که فهمیدم این هست:
۱- هر کامپایلر یه سری هدر تعریف شده برای خودش رو داره که حتی ممکن هست اگه ما هدر جدیدی تعریف کنیم نتونه کامپایل کنه.
۲- توی visual studio برای اینکه app ما بتونه از headerهای عمومی تعریف شده استفاده کنه باید تیک empty project رو بزنیم در غیر اینصورت باید دستی هدرها را کپی کنیم براش.

درست متوجه شدم ؟

(من هر چند سال یکبار گذرم به C++‎‎‎ میخوره ولی دونستنش خالی از لطف نیست)

rahnema1
یک شنبه 10 اسفند 1393, 12:31 عصر
هر کامپایلر یه سری هدر تعریف شده برای خودش رو داره که حتی ممکن هست اگه ما هدر جدیدی تعریف کنیم نتونه کامپایل کنه.

یه سری هدر ها که مخصوص کتابخانه استاندارد هستند در کامپایلرهایی که از استاندارد پیروی می کنند وجود داره که کاری که انجام می دهند همه مطابق با استاندارد هست و در همه یکسانه اما نحوه پیاده سازی اون تابعها یا کلاسها در هدرهای کامپایلرهای مختلف متفاوته بنابراین مثلا اگه شما یک هدر از اینترنت گیر آوردید و مثلا متعلق به gcc باشه و بخواهید در vs استفاده کنید با اشکال مواجه می شید. چون هر کامپایلری علاوه بر استاندارد، یه چیزهایی هم مختص خودش داره که در هدر ها از اونها استفاده می کنه ولی از چشم کاربر مخفیه و مثلا کاربر هم لزومی نداره بدونه که اونها چی هستن
نکته دیگه اینه که بعضی فایلهای h شامل اعلان تابع هستند و شامل تعریف کامل اونها نیستند. تعریف کامل معمولا در فایلهایی به نام lib قرار داره


۲- توی visual studio برای اینکه app ما بتونه از headerهای عمومی تعریف شده استفاده کنه باید تیک empty project رو بزنیم در غیر اینصورت باید دستی هدرها را کپی کنیم براش.

درست متوجه شدم ؟

اگه منظورتون stdafx هست که اون هدرهای کامپایل شده هست که موجب میشه جریان کامپایل سریعتر انجام بگیره نمیشه اسمش را عمومی گذاشت
کافیه از #include استفاده کنیم تا هدر ها به برنامه اضافه بشن



(من هر چند سال یکبار گذرم به C++‎‎‎ میخوره ولی دونستنش خالی از لطف نیست)

امیدوارم بیشتر گذرتون به ++c بخوره!!

SajadT2010
یک شنبه 10 اسفند 1393, 12:39 عصر
کافیه از #include استفاده کنیم تا هدر ها به برنامه اضافه بشن

من توی vs مثلا #include <iostream> استفاده میکردم میگفت وجود نداره. الان تنها فرقی که توی ساخت پروژه توی ویزاد انجام دادم این بود که تیک empty project زدم و دیگه به اون خطا برخورد نکردم. دلیلش چی هست ؟



امیدوارم بیشتر گذرتون به ++c بخوره!!
آخرین بار سه سال پیش بود که استفاده کردم. الان هم دارم یه پروژه PHP انجام میدم که اگه میخواستم این پینگ‌ها رو با اون انجام بدم مشکلساز میشد برا همین از c++ عزیز کمک گرفتم

rahnema1
یک شنبه 10 اسفند 1393, 12:52 عصر
دقیقا نمیدونم احتمالا مشکل از precompiler headers یا stdafx بوده

Mr.reCoder
یک شنبه 10 اسفند 1393, 14:08 عصر
درود،

خطوط اول رو به این صورت تغییر بدید:
#include "windows.h"
#include "conio.h"
#include "tchar.h"
#include "Iphlpapi.h"
#include "Icmpapi.h"
#include <iostream>
#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Iphlpapi.lib")

using namespace std;

با دستور زیر کامپایل کنید (فایل با نام src.cpp ذخیره شده است):

cl src.cpp

البته من با استفاده از sdk و اجرای VsDevCmd.bat در cmd اجرا و کامپایل کردم. ضمیمه شد!

SajadT2010
یک شنبه 24 اسفند 1393, 13:41 عصر
یه مشکلی که خوردم این برنامه زمان رو رند میکنه به سمت پایین. یعنی 0.1 رو میگه 0 من قصد دارم به سمت بالا رند بشه و متاسفانه با +1 قضیه حل نمیشه.
هیچ دیتا تایپی میشه بجای ULONG استفاده کرد که به سمت بالا رند بکنه ؟



typedef struct icmp_echo_reply {
IPAddr Address; // Replying address
ULONG Status; // Reply IP_STATUS
ULONG RoundTripTime; // RTT in milliseconds
USHORT DataSize; // Reply data size in bytes
USHORT Reserved; // Reserved for system use
PVOID Data; // Pointer to the reply data
struct ip_option_information Options; // Reply options
} ICMP_ECHO_REPLY, *PICMP_ECHO_REPLY;

rahnema1
یک شنبه 24 اسفند 1393, 18:49 عصر
یعنی منظورتون اینه که 0.1 میلی ثانیه بوده؟ از کجا می دونید 0.1 بوده؟

SajadT2010
یک شنبه 24 اسفند 1393, 19:19 عصر
مقدارش مهم نیست. مهم برام اینه که اعداد بین 0 تا <1 (کمتر از یک) رو رند میکنه به 0 و من به مشکل میخورم. چون پینگها هم اکثرا شبکه داخلی هست بین این رنج هستند.
الان مشکل اصلی من اینه که ULONG میاد اعداد رو اعشارش حذف میکنه و نتیجه اینکه رند میشه به پایین مثلا:
0.9 میشه 0 اما من میخوام 1 برگرده
3.66 میشه 3 اما من میخوام 4 برگرده
هیچ دیتا تایپی هست که این خاصیت رو داشته باشه؟

rahnema1
یک شنبه 24 اسفند 1393, 19:26 عصر
مقدارش مهم نیست. مهم برام اینه که اعداد بین 0 تا <1 (کمتر از یک) رو رند میکنه به 0 و من به مشکل میخورم. چون پینگها هم اکثرا شبکه داخلی هست بین این رنج هستند.
الان مشکل اصلی من اینه که ULONG میاد اعداد رو اعشارش حذف میکنه و نتیجه اینکه رند میشه به پایین مثلا:
0.9 میشه 0 اما من میخوام 1 برگرده
3.66 میشه 3 اما من میخوام 4 برگرده
هیچ دیتا تایپی هست که این خاصیت رو داشته باشه؟

ببینید اینجا بر اساس میلی ثانیه دقت زمان محاسبه می شه و دقت پایین تر از اون را نمیتونه اندازه بگیره مثلا دقت زمانی در حد صدم میلی ثانیه نداره
شما از کجا متوجه شدید که 3.66 هست با این دقت زیاد؟

SajadT2010
یک شنبه 24 اسفند 1393, 19:36 عصر
ببینید متاسفانه این رند شدن توی ویندوز وجود داره. وقتی پینگ میگیری که بین رنج مد نظر من باشه با علامت <1 نشون میده و خلاص. در حالی که حقیقتا ممکنه عدد واقعی 0.50 باشه. مثلا من نتیجه پینگ توی لینوکس رو میذارم



sajad@Tahernejad:~$ ping -c 1 -W 1000 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.020 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.020/0.020/0.020/0.000 ms




اینم نتیجه توی ویندوز



C:\Users\ST>ping 127.0.0.1 -n 1 -w 1000


Pinging 127.0.0.1 with 32 bytes of data:
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128

Ping statistics for 127.0.0.1:
Packets: Sent = 1, Received = 1, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms

مشکل من این هست که الان این برنامه خروجی که بگیریم اگه نتیجه پینگ destanation host unrechable هم باشه باز هم 0 برمیگردونه. من اگه بتونم این unrechable رو با -1 نشون بدم یا مابقی نتایج رو رند به بالا کنم مساله حل میشه

rahnema1
یک شنبه 24 اسفند 1393, 19:48 عصر
شما Status که داخل ICMP_ECHO_REPLY قرار داره را چک کنید که انوع مقداری که داره در لینک زیر هست از جمله:
IP_SUCCESS
IP_DEST_NET_UNREACHABLE
و ..

https://msdn.microsoft.com/en-us/library/windows/desktop/aa366053(v=vs.85).aspx

SajadT2010
یک شنبه 24 اسفند 1393, 19:54 عصر
به این شکل حلش کردم: همه استاتوزهای غیر از
IP_SUCCESS رو مقدار دادم -1 و آخر سر نتایج رو +1 کردم. الان اگه پینگ جواب بده و کمتر از 1 باشه رو 1 نشون میده و اگه به هر دلیل جواب نده 0 برمیگرده.
مرسی از شما.