PDA

Tam Sürümünü Görmek İçin : ping işlemi ve system()


sekizbit
03/06/2007, 02:43
Merhaba, c++ ile ağdaki pclerin online olup olmadıklarını kontrol etmek istiyorum. Bunu system() işlevine ping parametresini göndererek yapabilirim ancak pingten gelen cevabı yazdığım program içersinde nasıl okuyacağımı bilmiyorum. Bu konuda bilgisi olan veya, system dışında nasıl ping edebilecğeimi söyleyebilecek biri varsa sevinirim.

Ayrıca denediklerimden gördüğüm kadarı ile system() ile harici bir işlev başlattığımızda, başlattığımız program sonlanmadan esas yazılımımız işine devam etmiyor. mesela system("calc.exe") yi çağırdıktan sonra calc.exe yi yine yazdığımız program içersinden nasıl kapatabiliriz ? veya yazılımın calc.exe yi açtıktan sonra kapanmasını beklemeden işine devam etmesini nasıl sağlayabiliriz ?


acehreli
03/06/2007, 05:28
system'den daha iyi bir cozum icin Win32'deki CreateProcess benzeri bir isleve bakabilirsin.

Bu soylediklerim Linux icin galiba ama Windows'da da calisabilir...

system'in belgesinden anladigima gore, calistirdigi programin dOndUrdugu degeri system'in dOnUs degeri olarak okuyabiliyormusuz. Ama onu wait() islevinde anlatildigi sekilde WEXITSTATUS makrosundan gecirmemiz gerekiyormus.

Bendeki ping'in belgesinden de su dOnUs degerlerini dOndUrdugunu anliyorum:

0: en az bir tane yanit alindi
1: yanit almadik (bunu deneme yanilma ile buldum aslinda)

Bu bilgiler system'i kullanarak cozmene yeter herhalde ama ben de bir program yazdim:


#include <iostream>
#include <string>
#include <sstream>
#include <cassert>
#include <stdexcept>

using namespace std;

// Bu kadar paket gondermeye calisacagiz
const int pingPaketAdedi = 2;
const int pingBasarili = 0;
const int pingBasarisiz = 1;

string pingKomutuYap(const string & pc)
{
ostringstream komut;
komut << "ping"
<< " -c " << pingPaketAdedi
<< ' ' << pc
<< " > /dev/null";

return komut.str();
}

class OnlineHatasi : public std::runtime_error
{
int systemSonucu_;

public:

explicit OnlineHatasi(int systemSonucu)
:
std::runtime_error("PC online hatasi"),
systemSonucu_(systemSonucu)
{}

int systemSonucu() const
{
return systemSonucu_;
}
};

bool pcOnline(const string & pc)
{
const string pingKomutu = pingKomutuYap(pc);
const int systemSonucu = system(pingKomutu.c_str());

if (systemSonucu == -1) {
throw OnlineHatasi(systemSonucu);
}
else
{
const int pingSonucu = WEXITSTATUS(systemSonucu);

switch (pingSonucu)
{
case pingBasarili:
return true;
break;

case pingBasarisiz:
return false;
break;

default:
throw OnlineHatasi(systemSonucu);
break;
};
}

// Buraya gelmis olamayiz
assert(0);
return false;
}

void onlineBilgisiVer(ostream & cikis, string const & pc, bool online)
{
cikis << pc << " online";

if (!online)
{
cikis << " DEGIL";
}
}

void pcOnlineDene(const string & pc)
{
cout << "pcOnline'i " << pc << " icin deniyoruz" << endl;
try
{
const bool sonuc = pcOnline(pc);
onlineBilgisiVer(cout, pc, sonuc);
cout << endl;
}
catch (const OnlineHatasi & hata)
{
cerr << "HATA: system'in dOnUs degeri "
<< hata.systemSonucu() << '\n';
}
}

int main()
{
pcOnlineDene("192.168.1.1");
pcOnlineDene("192.168.1.10");
}


Ali

sekizbit
03/06/2007, 13:00
Malesef yazdığınız programı windows üzerinde çalıştıramadım. WEXITSTATUS makrosunu tanımlamak için wait.h ı include etmem gerekti, internetten bulup yükledim. wait.h içinden 4 tane daha kütüphane istedi, internetten bulup onlarıda yükledim, bu yüklenen kütüphaneler kendi içlerinden başka kütüphaneler include etmişler onlarıda bul derken işin sonu gelmedi :)

acehreli
03/06/2007, 18:22
Zaten system'in isini bitirmesini beklemek istemedigin icin en iyisi CreateProcess'i kullanmak. Surada kisa bir ornek var:

http://msdn2.microsoft.com/en-us/library/ms682512.aspx

ping'in dOndUrdugu degeri de sanirim GetExitCodeProcess ile alabiliyormussun:

http://msdn2.microsoft.com/en-us/library/ms683189.aspx

Ben bunlari cok uzun zamandir kullanmadim; belki daha iyi yontemler vardir. (?)

Ali

sekizbit
03/06/2007, 23:03
GetExitCodeProcess olayını anlamadım, içine gönderecğeim parametleri falan çözemedim.

acehreli
03/06/2007, 23:28
GetExitCodeProcess, calistirilmis olan bir "process"in dOnUs degerini almak icin kullaniliyor. ping'i CreateProcess'le baslattiktan sonra basarili olup olmadigini anlamak icin...

GetExitCodeProcess iki parametre aliyor:

BOOL WINAPI GetExitCodeProcess(
HANDLE hProcess,
LPDWORD lpExitCode
);

hProcess'i CreateProcess'e gonderdigin PROCESS_INFORMATION yapisinin icinde bulacaksin. CreateProcess ping'i calistirinca onun icin kullandigi HANDLE'i o yapinin icine yazacak.

Iste GetExitCodeProcess'i cagirirken kullanacagin hProcess o olacak.

GetExitCodeProcess'in ikinci parametresi de ping'in dOndUrdugu deger olacak:



HANDLE pingHandle = /* CreateProcess'e gonderdigin PROCESS_INFORMATION'dan al */
DWORD pingSonucu = -1;
GetExitCodeProcess(pingHandle, &pingSonucu);

if (pingSonucu == STILL_ACTIVE) {
// program hAlA calisiyor demek...
}
else {
// program sonuclanmis
if (pingSonucu == 0) {
// online
}
else {
// online DEGIL
}
}


Ali

sekizbit
05/06/2007, 16:03
Ali bey yardımlarınız için teşekkür ederim. Ama durum itibari ile, CreateProcess yerine system() kullanmam sanırım daha çok işime yarıyor. çünkü benim işime devam etmem için ping işleminin bitmiş olması gerekiyor. (CreateProcess zor geldi de denilebilir:) )

Sizin en başta yazdığınız kod için, elimin altında linux kurulu makina yok ancak üniversitede linux makina üzerinde dönem bittiği için artık kısıtlı olan bir ssh hesabım var.
programı derleyebiliyorum sorun çıkmıyor, ancak ping işlemine yasak koydukları için çalışırken sonucunu göremiyorum :D

Esas sorum ise WEXITSTATUS makrosunu windows üzerinde nasıl çalıştırabilirim ? yada yerine kullanabileceğim bildiğiniz bi makro varmı ?

IDE olarak, Dev C++ kullanıyorum.

acehreli
05/06/2007, 20:33
system'in dOnUs degeri standart tarafindan belirlenmemis. Onun icin senin MSDN'e bakman gerekiyor:

http://msdn2.microsoft.com/en-us/library/277bwbdz(VS.80).aspx

Anladigim kadariyla hatali durumlar disinda, system galiba ping'in dOndUrdugu degeri dOndUruyor. Yani belki de degeri WEXITSTATUS makrosundan gecirmene gerek yok. Bir kac denemeyle bunu anlayabilirsin aslinda.

Yapman gereken diger sey, senin ping'inin hangi durumda ne deger dOndUrdugunu ogrenmek. Bunu da deneyerek bile bulabilirsin.

Ali

Revlis
05/06/2007, 21:03
cevap geliyorsa sistem açık değil midir zaten ?

acehreli
05/06/2007, 21:45
Tabii de, ping'i kendisi gerceklestirmiyor. system("ping vs. vs.") komutunu calistirarak disaridaki ping programini kullaniyor. Bu durumda cevap gelip gelmedigin anlamaya calisiyor.

Ali

Revlis
05/06/2007, 23:10
asdsad anladım :D..
ping.exe yi çalıştırmak çok yanlış. ama amaç komut satırından bir şey okumaksa
ping 123.123.123.123 > temp.txt
olarak çalıştırırsın
temp.txt yi okutursun..
Ama ping i kendi programından atsan daha mantıklı ve doğru

sekizbit
06/06/2007, 16:48
Bu kadar tembelleştiğime inanamıyorum :(


int i ;
i = system("ping 160.75.2.20 -n 2");
cout<<i<<"\n" ;



şu kadarcık kod parçasını yazıp denemek yerine, bir sürü soru sordum. Bi kaç deneme yaptım, eğer işlem gerçekleştirilemezse dönüş değeri 1 oluyor.

eğer işlem gerçekleştirilir, ama karşı bilgisayardan cevap alinamazsa yine 1 oluyor.

eğer karşı bilgisayardan cevap gelmişse 0 oluyor.

şimdilik işimi görüyo zaten bu:)

Herkese çok teşekkür ederim.

ortug
06/06/2007, 20:11
peki bu tür işlemler için windows'ta linux'taki pipe benzeri bir yapı var mı?
burda sadece dönen değeri okumamız yeterli oluyor. Ya programa komut da göndermemiz gerekirse

acehreli
07/06/2007, 00:32
Son calistigim projede Windows'da "named pipe" kullanilmisti:

http://msdn2.microsoft.com/en-us/library/aa365150.aspx

Ali