2011-07-11 145 views
1

我以前見過這個問題,但我從未找到有效的答案。我需要獲取我的服務器連接的計算機的顯式IP地址(即123.456.789.100)和端口號,以便將該信息轉發給其他客戶端。我在Windows 7(Home Premium),Visual Studio 2010 Professional上使用WinSock2.h - 製作「C++控制檯應用程序」。這是一個TCP連接。 這裏是我到目前爲止的代碼:如何從Windows套接字(C++)獲取連接主機的IP地址?

sockaddr_in* addr = new sockaddr_in; 
int addrsize = sizeof(addr); 
getsockname(clientSock, (sockaddr*)addr, &addrsize); 
char* ip = inet_ntoa(addr->sin_addr); 
int port = addr->sin_port; 
printf("IP: %s ... PORT:%d\n", ip, port); 

這總是給我205.205.205.205的IP和52685的端口每次。我已經嘗試過替代方案,包括gethostbyname,它可以工作,但我需要實際的IP本身。我也嘗試getpeername()代替getsockname(),但結果是相同的。我在路由器後面,但到目前爲止,我在同一臺計算機上同時使用了服務器和客戶端。

在此先感謝您的幫助!

回答

3

getpeername()是你想要使用的函數。

一些錯誤,我在你的代碼中看到:

1)你在堆中分配地址。不需要這麼做,只需聲明「sockaddr_in addr;」在堆棧上,並將& addr(而不是addr)傳遞給getpeername()調用。

2)addrsize被設置爲指針(例如4或8),而不是)實際SOCKADDR_IN的大小,這意味着...

3)getsockname(可能是失敗的大小,但你不知道,因爲

4)你不檢查getsockname()的返回值,看看是否有錯誤或沒有,這意味着你是

5)結果在getsockname()/ getpeername()調用之前,看到的只是顯示任意垃圾數據(* addr),因爲調用失敗而沒有向廣告寫入任何內容dr結構。噢,還有一件事......一定要在ntohl()調用中包含對addr.sin_addr的引用,並且在ntohs()調用中引用addr.sin_port,否則您將獲得它們在運行小端(基於英特爾架構)計算機時以大端形式存在,這不是您想要的。

+0

是的,你是對的,它是拋出一個錯誤,我沒有檢查它。非常感謝您的解決方案。 – Sefu

1

是的,你是對的,它是拋出一個錯誤,我沒有檢查它。非常感謝您的解決方案。最後的代碼對我來說如下:

sockaddr_in addr; 
int addrsize = sizeof(addr); 
int result = getpeername(clientSock, (sockaddr*) &addr, &addrsize); 
printf("Result = %d\n", result); 
char* ip = inet_ntoa(addr.sin_addr); 
int port = addr.sin_port; 
printf("IP: %s ... PORT: %d\n", ip, port); 

而這讓我得到了正確的結果。我感謝您的幫助。謝謝!

相關問題