Tôi có một máy chủ có ổ cắm đến từ một máy khách. Tôi cần có địa chỉ IP của ứng dụng khách từ xa. Đã thử tìm kiếm trên google in_addr
nhưng hơi rắc rối một chút. Bất kỳ đề xuất nào?Lấy địa chỉ nguồn của một kết nối ổ cắm đến
Trả lời
Bạn cần có chức năng getpeername
. Hướng dẫn kết nối mạng lớn của Beej có số page about it. Dưới đây là một mẫu mã từ đó:
// assume s is a connected socket
socklen_t len;
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
int port;
len = sizeof addr;
getpeername(s, (struct sockaddr*)&addr, &len);
// deal with both IPv4 and IPv6:
if (addr.ss_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
port = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
} else { // AF_INET6
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
port = ntohs(s->sin6_port);
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
}
printf("Peer IP address: %s\n", ipstr);
+1. Tuy nhiên, chúng ta không phải giải phóng bộ nhớ cho điều này? – iammilind
Tôi nhận thấy 'struct sockaddr_in * s' đổ bóng' s' vào ổ cắm ngoài. Có một biến bóng không phải là lý tưởng. –
là có cách để lấy socketDescriptor từ địa chỉ – Bionix1441
Vì bạn nói rằng nó là một kết nối đến từ một khách hàng, như một thay thế cho getpeername
bạn chỉ có thể lưu các địa chỉ đó được trả về bởi các accept()
cuộc gọi, trong lần thứ hai và thứ ba thông số.
Giả sử bạn đang sử dụng accept()
để chấp nhận kết nối ổ cắm đến, getpeername()
là không cần thiết. Thông tin địa chỉ có sẵn thông qua tham số thứ 2 và thứ 3 của cuộc gọi accept()
.
Dưới đây là câu trả lời của Eli sửa đổi để làm điều đó mà không getpeername()
:
int client_socket_fd;
socklen_t len;
struct sockaddr_storage addr;
char ipstr[INET6_ADDRSTRLEN];
int port;
len = sizeof addr;
client_socket_fd = accept(server_socket_fd, (struct sockaddr*)&addr, &len);
// deal with both IPv4 and IPv6:
if (addr.ss_family == AF_INET) {
struct sockaddr_in *s = (struct sockaddr_in *)&addr;
port = ntohs(s->sin_port);
inet_ntop(AF_INET, &s->sin_addr, ipstr, sizeof ipstr);
} else { // AF_INET6
struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
port = ntohs(s->sin6_port);
inet_ntop(AF_INET6, &s->sin6_addr, ipstr, sizeof ipstr);
}
printf("Peer IP address: %s\n", ipstr);
+1 để trực tiếp sử dụng 'accept()'. Tuy nhiên, chúng ta không phải giải phóng bộ nhớ cho điều này? – iammilind
@iammilind: Tôi không nghĩ rằng bất kỳ bộ nhớ nào cần được giải phóng — Tôi không thể thấy bất kỳ phân bổ động nào đang được thực hiện. Tất cả được thực hiện với các biến được phân bổ tĩnh. –
in_addr là IPv4-cụ thể, dù sao – bortzmeyer
man getpeername
–thấy (..) chức năng inet_ntoa trong linux .. 'người đàn ông inet_ntoa'. nó dễ dàng hơn inet_ntop theo ý kiến của tôi và nhu cầu bao gồm arpa/inet.h. đây là một ví dụ: http://www.binarytides.com/programming-udp-sockets-c-linux/ – mhk