2010-06-17 63 views
24

Tôi đang viết máy chủ/máy khách đơn giản và cố gắng lấy địa chỉ IP của khách hàng và lưu nó ở phía máy chủ để quyết định khách hàng nào sẽ vào phần quan trọng. Tôi googled nó nhiều lần nhưng không thể tìm thấy cách thích hợp để có được địa chỉ IP từ cấu trúc sock.Cách lấy địa chỉ ip từ cấu trúc sock trong c?

Tôi tin rằng đây là cách để nhận IP từ cấu trúc sock sau khi máy chủ chấp nhận yêu cầu từ máy khách. Cụ thể hơn trong c sau khi máy chủ thực hiện

csock = accept(ssock, (struct sockaddr *)&client_addr, &clen) 

Cảm ơn

+0

Chỉ cần nói với mọi người ở đây rằng câu trả lời đã chọn là câu trả lời rất tệ về một số lần đếm. Xin vui lòng, xin vui lòng, vì lợi ích của tất cả các lập trình viên khác, không sử dụng nó. – Omnifarious

Trả lời

36

OK giả sử bạn đang sử dụng IPV4 sau đó làm như sau:

struct sockaddr_in* pV4Addr = (struct sockaddr_in*)&client_addr; 
struct in_addr ipAddr = pV4Addr->sin_addr; 

Nếu sau đó bạn muốn địa chỉ ip như là một chuỗi sau đó làm như sau:

char str[INET_ADDRSTRLEN]; 
inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN); 

IPV6 cũng khá dễ dàng ...

struct sockaddr_in6* pV6Addr = (struct sockaddr_in6*)&client_addr; 
struct in6_addr ipAddr  = pV6Addr->sin6_addr; 

và nhận được một chuỗi là gần như giống hệt với IPV4

char str[INET6_ADDRSTRLEN]; 
inet_ntop(AF_INET6, &ipAddr, str, INET6_ADDRSTRLEN); 
+2

Bạn quên chuyển bộ đệm 'str' sang' inet_ntop() '. Và 'sin_addr' là một cấu trúc - người ta phải sử dụng' sin_addr.s_addr'. Cần lưu ý rằng địa chỉ IPv4 được lưu trữ trong thứ tự byte mạng và để xem nó như là một số hex sẽ cần sử dụng 'ntohl (pV4Addr-> sin_addr.s_addr)'. – Dummy00001

+0

Điểm lấy ... bạn cũng bỏ lỡ của tôi không sử dụng chữ thường "in6_addr";) Trên mặt trước ntohl tôi không thường bận tâm vì tôi vẫn có thể kiểm tra bình đẳng (được cung cấp cả trong thứ tự mạng) và nó sẽ phá vỡ inet_ntop (phải không?). – Goz

+2

Câu hỏi này được gắn thẻ C - bạn không thể bỏ qua 'struct' trong các kiểu như' struct sockaddr_in * '. Ngoài ra, phương thức IPV4 nên sử dụng 'struct in_addr' thay vì' int' để lưu địa chỉ, analagous vào phương thức IPV6 mà bạn hiển thị. – caf

21

Giả sử client_addr là một struct sockaddr_in (mà nó thường là). Bạn có thể nhận địa chỉ IP (dưới dạng số nguyên không dấu 32 bit) từ client_addr.sin_addr.s_addr.

Bạn có thể chuyển đổi nó thành một chuỗi theo cách này:

printf("%d.%d.%d.%d\n", 
    int(client.sin_addr.s_addr&0xFF), 
    int((client.sin_addr.s_addr&0xFF00)>>8), 
    int((client.sin_addr.s_addr&0xFF0000)>>16), 
    int((client.sin_addr.s_addr&0xFF000000)>>24)); 
+27

Bạn nên sử dụng inet_ntoa() thay vì không sử dụng các bit theo cách thủ công. –

+12

'inet_ntoa' không an toàn cho luồng, mặc dù điều đó có thể không quan trọng đối với hầu hết các trường hợp được sử dụng. Một phương án an toàn là 'inet_ntop'. – jweyrich

+3

Điều này sẽ không hoạt động đối với bất kỳ kiến ​​trúc cuối lớn nào. – Ternvein

26

Cách dễ dàng và chính xác cho giải nén địa chỉ IP và số cổng sẽ là:

printf("IP address is: %s\n", inet_ntoa(client_addr.sin_addr)); 
printf("port is: %d\n", (int) ntohs(client_addr.sin_port)); 

trả lời chấp nhận của Soapbox sẽ không chính xác cho mọi kiến ​​trúc. Xem Big and Little Endian.

Các vấn đề liên quan