2010-01-20 1 views
4

В следующем коде я хотел бы извлечь IP-адрес подключенного клиента после принятия входящего соединения. Что мне делать после accept(), чтобы достичь этого?Извлечь IP из соединения, которое прослушивает и принимает в программировании сокетов в Linux в c

int sockfd, newsockfd, portno, clilen; 
portno = 8090; 
clilen = 0; 
pthread_t serverIn; 
struct sockaddr_in serv_addr, cli_addr; 
sockfd = socket(AF_INET, SOCK_STREAM, 0); 
if (sockfd < 0) 
{ 
    perror("ERROR opening socket"); 
} 
bzero((char *) & serv_addr, sizeof (serv_addr)); 
serv_addr.sin_family = AF_INET; 
serv_addr.sin_port = htons(portno); 
serv_addr.sin_addr.s_addr = INADDR_ANY; 
if (bind(sockfd, (struct sockaddr *) & serv_addr, sizeof (serv_addr)) < 0) 
{ 
    perror("ERROR on binding"); 
} 

listen(sockfd, 5); 
clilen = sizeof (cli_addr); 
newsockfd = accept(sockfd, (struct sockaddr *) & cli_addr, &clilen); 
+0

У вас уже есть это в cli_addr, не так ли? – zneak

+0

@zneak Мне нужен IP-адрес для клиента, который подключается ко мне – SjB

+0

Да, это то, что 'accept()' возвращает вам в 'cli_addr'! Вам нужно только отформатировать его - посмотрите ответы ниже. –

ответ

6
+5

Не нужно вызывать 'getpeername()' as' accept() 'заполняет адрес клиента во втором аргументе. –

+1

Beej's - очень приятное вступительное слово. – Flame

+0

(Извиняюсь за ошибочное голосование выше комментария как шума.) –

1

Вы можете последовать этому примеру:

#include <sys/types.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <stdio.h> 

{ 
    int s; 
    struct sockaddr_in peer; 
    int peer_len; 
    . 
    . 
    . 
     /* We must put the length in a variable.    */ 
    peer_len = sizeof(peer); 
     /* Ask getpeername to fill in peer's socket address. */ 
    if (getpeername(s, &peer, &peer_len) == -1) { 
     perror("getpeername() failed"); 
     return -1; 
    } 

     /* Print it. The IP address is often zero because  */ 
     /* sockets are seldom bound to a specific local  */ 
     /* interface.           */ 
    printf("Peer's IP address is: %s\n", inet_ntoa(peer.sin_addr)); 
    printf("Peer's port is: %d\n", (int) ntohs(peer.sin_port)); 
    . 
    . 
    . 
} 
11

Ваш cli_addr уже содержит IP-адрес и номер порта, подключенного клиента после accept() возвращается успешно, в том же формате, что и ваш serv_addr переменной. Используйте inet_ntop для преобразования IP в строку.

+0

Мне нужен IP-адрес для клиента, который подключается ко мне, который использует getpeername() – SjB

+3

Хм, вы где-то смущены. accept() возвращает клиентский IP-адрес и порт клиента во втором аргументе. Вам ** не нужно ** для вызова getpeername(), поскольку это дает вам точную точную информацию. –

+2

Приобретено. Я думаю, что путаница проистекает из того факта, что sockaddr содержит IP как 4 байта, в то время как OP нуждается в нем в тексте. –

2

Я думаю, getpeername() не нужен - адрес клиента уже заполнен cli_addr по вызову accept().

Вам нужно всего лишь использовать inet_ntop(), getnameinfo() или gethostbyaddr(), чтобы распечатать или получить дополнительную информацию.

1

API описан на страницах руководства. Вы можете либо просмотреть их с консоли, начиная с man socket и следовать ссылкам на man getpeername или использовать Konqueror, который отлично отображает ссылки, если вы запрашиваете адрес #socket. В моем случае на Kubuntu необходимо было установить пакет manpages-dev.