Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > определение ip клиента.


Автор: Lorido 12.8.2009, 02:03
Задача ставилась определить ip подключившегося сокета клиента.
Нашёл пример использования, скокпипастил smile  Однако выдаёт совсем не те адреса при тестовом прогоне. Тыкните пальцем где неточность.
Код

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>    
#include <iostream>    
#include <arpa/inet.h>

int main(){
   int sock_fd;
   int newsock_fd;
   struct sockaddr_in addr;
   struct sockaddr_in ss;
   struct sockaddr_in new_socket;
   unsigned int len;
   unsigned int addr_len;

   sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

   addr.sin_family = AF_INET;
   addr.sin_addr.s_addr = htonl(INADDR_ANY);
   addr.sin_port = htons(15000);
   bind(sock_fd,(struct sockaddr*)&addr,sizeof(addr));
   listen(sock_fd,1);
   newsock_fd = accept(sock_fd,(struct sockaddr*)&new_socket,&addr_len); // Code blocks here

   // Assuming client has connected to the server.
   len = sizeof(ss);
   getpeername(sock_fd,(struct sockaddr*)&ss,&len);
   printf(inet_ntoa(ss.sin_addr));
   close(newsock_fd);
   close(sock_fd);
}



Заранее благодарю.

Автор: volkrey 12.8.2009, 06:33
посмотри, вот в этой строчке (возможно я и ошибаюсь) должен быть дескриптор нового сокета

getpeername(newsock_fd,(struct sockaddr*)&ss,&len);

Автор: bourne 12.8.2009, 06:46
Lorido, немного переделал твой сорец:
Код

#include <stdio.h>
#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")

int main(){
   int sock_fd;
   int newsock_fd;
   struct sockaddr_in addr;
   struct sockaddr_in ss;
   struct sockaddr_in new_socket;
   unsigned int len;
   int addr_len;
   WSADATA WSAData;

    if(WSAStartup (MAKEWORD(1, 1), &WSAData) != 0)
        printf("WsaStartup: %d\n", GetLastError());

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(7000);
   
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(sock_fd == -1)
        printf("socket_error: %d\n", GetLastError());

    if(bind(sock_fd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)) == -1)
        printf("bind_error: %d\n", GetLastError());

    if(listen(sock_fd,1) == -1)
        printf("listen_error: %d\n", GetLastError());

    addr_len = sizeof(struct sockaddr_in);
    newsock_fd = accept(sock_fd,(struct sockaddr*)&new_socket,&addr_len); // Code blocks here

   // Assuming client has connected to the server.
   len = sizeof(ss);

   getpeername(newsock_fd,(struct sockaddr*)&ss,&len);
   printf(inet_ntoa(ss.sin_addr));
   close(newsock_fd);
   close(sock_fd);
}

Автор: Lorido 12.8.2009, 12:43
Нет, всё не то. Второй вариант не подходит ввиду того, что это должно стоять на линукс сервере. А подключать при этом виндовую библиотеку не эстетично что ли.
Программа, код которой я скинул, возвращает айпи. Единственно что это не те айпи-адреса с которых проходит тест. Может есть вариант как получить адрес клиента каким нибудь другим способом?

поставил проверку
Код

if(getpeername(sock_fd,(struct sockaddr*)&ss,&len) == -1){
        printf("error");
}


Теперь постоянно валятся ошибки.
Просмотрел все примеры в гугле - всё точно так же. smile 
Я даже не знаю куда копать.

Автор: andrew_121 12.8.2009, 12:47
Lorido, Измени пару строк, и будет работать на Линукс.

Автор: Lorido 12.8.2009, 14:10
какие строки надо переделать?
меня больше интересует почему
Код

if(getpeername(sock_fd,(struct sockaddr*)&ss,&len) == -1){
        printf("error");
}

выкидывает ошибку.

Автор: GoldFinch 12.8.2009, 15:01
а что не boost::asio?

Автор: Lorido 12.8.2009, 15:05
ошибка нашлась
оказывается дейтсвительно в примере была ошибка.
Код

if(getpeername([color=red]newsock_fd[/color],(struct sockaddr*)&ss,&len) == -1){
        printf("error");
}

Проморгал. Вот что значит нехватка опыта. Спасибо всем кто помог.

Автор: andrew_121 12.8.2009, 15:05
Lorido, Вот:
Код


#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

int main(){
   int sock_fd;
   int newsock_fd;
   struct sockaddr_in addr;
   struct sockaddr_in ss;
   struct sockaddr_in new_socket;
   unsigned int len;
   int addr_len;

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(7000);
   
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if(sock_fd == -1)
        printf("socket_error: %s\n", strerror(errno));
    if(bind(sock_fd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in)) == -1)
        printf("bind_error: %s\n", strerror(errno));
    if(listen(sock_fd,1) == -1)
        printf("listen_error: %s\n", strerror(errno));
    addr_len = sizeof(struct sockaddr_in);
    newsock_fd = accept(sock_fd,(struct sockaddr*)&new_socket,&addr_len); // Code blocks here
   // Assuming client has connected to the server.
   len = sizeof(ss);
   getpeername(newsock_fd,(struct sockaddr*)&ss,&len);
   printf("%d\n", inet_ntoa(ss.sin_addr));
   close(newsock_fd);
   close(sock_fd);
    
    return 0;
}

И еще: http://www.rsdn.ru/article/unix/sockets.xml настоятельно рекомендую.


Цитата(GoldFinch @  12.8.2009,  15:01 Найти цитируемый пост)
а что не boost::asio? 

Мне тоже интересно.

Автор: GoldFinch 12.8.2009, 15:11
Код

#include <boost/asio.hpp>

int main()
{
        const unsigned short port = 15000;
        try
        {
                boost::asio::io_service io;
                boost::asio::ip::tcp::acceptor acceptor(io,
                        boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(),port) );
                boost::asio::ip::tcp::socket s(io);
                acceptor.accept(s);
                std::cout << s.remote_endpoint() << std::endl;
        }
        catch (std::exception& e)
        {
                std::cerr << e.what() << std::endl;
                return 1;
        }
        return 0;
}

как-то так

Автор: andrew_121 12.8.2009, 15:16
GoldFinch, Красотища!

Автор: Олег2005 12.8.2009, 22:11
Небольшой коммент:

listen(sock_fd,backlog)

На самом деле во многих TCP-модулях различных ОС истинное значение длины очереди буфера для приема входящих соединений расчитывается по формуле: 
                                                               backlog * 3 / 2 + 1
и listen(sd, 0) разрешит принять одно соединение,  listen (sd, 5)  - 8. 

Потому значение backlog=1 практически не используют.........

Автор: xvr 13.8.2009, 11:16
Кстати, после 
Код

 newsock_fd = accept(sock_fd,(struct sockaddr*)&new_socket,&addr_len); 
в new_socket УЖЕ лежит адрес подключившегося клиента. Нафига еще getpeername звать?

Автор: xrays777 13.8.2009, 13:11
inet_ntoa()
ntohs()


воспользуйся этими функциями и будет тебе счастье

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)