2010-11-15 24 views
5

a clone of inetd yazıyor ve bu bağlantıya bağlanan istemcinin IP'sini ve bağlantı noktasını yazdıran bir sunucuyu çalıştırmam gerekiyor. Bunu yapmak içinSoket Tanımlayıcısından IP/Bağlantı Noktası Kurtarılıyor

Ben soket tanımlayıcısı ile STDIN ve STDOUT üzerine itibariyle my initial solution gereken bilgileri içeren sockaddr_in yapısını, bulmaktı. Bununla birlikte, getsockname() ile yapılıyorsa, tüm bitler 0 olarak ayarlanmış boş bir yapıya dönüyor.

Yaklaşımımın nesi yanlış? IP/Port'u kurtarmak için kullanabileceğim başka yaklaşımlar var mı?

Teşekkür

cevap

8

R .. işaret ettiği gibi, getpeername kullanmalısınız. Hem bu işlev hem de getsockname ilk argümanı olarak bir dosya tanıtıcısı alır, bir akış işaretçisi (FILE *). Standart girdi için dosya tanımlayıcısını almak için fileno(stdin)'u kullanın (veya sabit olarak STDIN_FILENO'a sabit kodlayın). Ayrıca

, getsockname ve getpeername son argüman socklen_t bir işaretçi değil, bir sabit olmalı ve TCP/IP için bir sockaddr_in kullanmalıdır:

struct sockaddr_in peeraddr; 
socklen_t peeraddrlen = sizeof(peeraddr); 
getpeername(STDIN_FILENO, &peeraddr, &peeraddrlen); 

eksiksiz bir örnek here bakınız.

+0

OP, "overwriting" stdin'i ve stdout'u, en iyi ihtimalle yanlış bir şekilde bildirilen soket için dosya tanımlayıcısından bahsetmişti, ancak değiştirmenin yanlış yapıldığını ve stdin'in (fd 0) aslında bir soket olmadığını gösteriyor olabilir ... –

+0

@R .., Kodu https://github.com/konr/Licio/blob/master/05/time adresinden kontrol edin.d –

+1

Dunno bu * sorun * ise, 'void *' için gerçekten çirkin bir ikame dışında 'struct sockaddr 'kullanmak her zaman bir hatadır. Asla "struct sockaddr" türünde gerçek nesneler olmamalıdır. Her zaman gerektiği gibi struct sockaddr_in, struct sockaddr_in6 veya struct sockadd_storage işlevlerini kullanın. –

3

kullanın getpeername. Sorununuzdan şüpheleniyorum ki, getsockname, soketin kendi (yerel) tarafına ait bilgileri döndürüyor. Bu, muhtemelen 0.0.0.0'a bağlı (yani herhangi bir arabirimden bağlantı kabul edebilir).

Düzenleme: Sanırım gerçek hata kodunu okuyarak buldum. Bu çizgi yanlıştır:

getsockname(stdin, &addr, sizeof(addr)); 

getsockname ve getpeername fonksiyonları üçüncü argüman değil, bir size_t olarak socklen_t * (a işaretçi) alır. getsockname prototipiyle bir başlık eklemeyi unutmazsanız, derleyici bu hatayı size anlatmalıdır. Ayrıca, daha önce de belirtildiği gibi, stdin yanlıştır. Deneyin:

socklen_t len = sizeof addr; 
getpeername(0, &addr, &len); 

veya (C99 için):

getpeername(0, &addr, (socklen_t[1]){sizeof addr}); 
Ayrıca dönüş değerini kontrol edilmelidir

; Eğer yapmış olsaydınız, hataların döndüğünü görecektiniz. Uzak İstemci için bu bilgiye ihtiyacınız varsa, getpeername() numaralı telefonu aramanız gerekir.

+0

kullanmazsınız, sonuç hala 0'dır. – konr

+2

Eğer getpeername() öğesi 0 döndürdüğü anlamına gelirse, bu işlevin başarılı olduğu anlamına gelir. – Simone