Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> отправка широковещательных дейтаграмм, не блокирующие сокеты 
:(
    Опции темы
Karser
  Дата 5.6.2007, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.5.2007

Репутация: нет
Всего: нет



используя winsock2 нужно:

Разработать два приложения клиент и сервер, предоставляющие пользователю возможность обмена сообщениями между различными машинами в сети. Передача данных должна быть организована через сокеты дейтаграмм на любой указанный пользователем IP.

В каждом приложении должна выводиться следующая информация: имя компьютера, имя хоста, IP адрес, информация об используемой версии библиотеки сокетов и максимальный размер дейтаграммы, которая может быть послана. Оба приложения должны использовать не блокирующий режим работы сокетов.

:shok 
Дополнительно реализовать возможность получения
           имени сервиса по указанному пользователем номеру порта 
           названия протокола по указанному пользователем номеру протокола

Прислал все это один добрый человек,учитывая маленькие сроки, прошу помощи 
конкретнее примеры работы с этим 

Ребят помогите исходником и примером  :wacko
PM MAIL   Вверх
ptr
Дата 6.6.2007, 15:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



Зачем "широковещательных дейтаграмм", если "на любой указанный пользователем IP".

Цитата(Karser @  5.6.2007,  19:32 Найти цитируемый пост)
конкретнее примеры работы с этим

А конкретнее. С UDP?


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Karser
Дата 7.6.2007, 01:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.5.2007

Репутация: нет
Всего: нет



Цитата(ptr @ 6.6.2007,  15:24)
Зачем "широковещательных дейтаграмм", если "на любой указанный пользователем IP".

Цитата(Karser @  5.6.2007,  19:32 Найти цитируемый пост)
конкретнее примеры работы с этим

А конкретнее. С UDP?

да, UDP. 
PM MAIL   Вверх
ptr
Дата 7.6.2007, 16:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



Ну посмотри вот это:
Код

#*******************************************************
#     MYCPLUS Sample Code - http://www.mycplus.com     *
#                                                     *
#   This code is made available as a service to our   *
#      visitors and is provided strictly for the      *
#               purpose of illustration.              *
#                                                     *
# Please direct all inquiries to saqib at mycplus.com *
#******************************************************/

// Module Name: Sender.c
//
// Description:
//    This sample sends UDP datagrams to the specified recipient.
//    The -c option first calls connect() to associate the 
//    recipient's IP address with the socket handle so that the 
//    send() function can be used as opposed to the sendto() call.
//
// Compile:
//    cl -o Sender Sender.c ws2_32.lib
//
// Command line options:
//    sender [-p:int] [-r:IP] [-c] [-n:x] [-b:x] [-d:c]
//           -p:int   Remote port
//           -r:IP    Recipient's IP address or hostname
//           -c       Connect to remote IP first
//           -n:x     Number of times to send message
//           -b:x     Size of buffer to send
//           -d:c     Character to fill buffer with
//
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>

#define DEFAULT_PORT            5150
#define DEFAULT_COUNT           25
#define DEFAULT_CHAR            'a'
#define DEFAULT_BUFFER_LENGTH   64

BOOL  bConnect = FALSE;                 // Connect to recipient first
int   iPort    = DEFAULT_PORT;          // Port to send data to
char  cChar    = DEFAULT_CHAR;          // Character to fill buffer 
DWORD dwCount  = DEFAULT_COUNT,         // Number of messages to send
      dwLength = DEFAULT_BUFFER_LENGTH; // Length of buffer to send
char  szRecipient[128];                 // Recipient's IP or hostname

//
// Function: usage
//
// Description:
//    Print usage information and exit
//
void usage()
{
    printf("usage: sender [-p:int] [-r:IP] "
           "[-c] [-n:x] [-b:x] [-d:c]\n\n");
    printf("       -p:int   Remote port\n");
    printf("       -r:IP    Recipients IP address or hostname\n");
    printf("       -c       Connect to remote IP first\n");
    printf("       -n:x     Number of times to send message\n");
    printf("       -b:x     Size of buffer to send\n");
    printf("       -d:c     Character to fill buffer with\n\n");
    ExitProcess(1);
}

//
// Function: ValidateArgs
//
// Description:
//    Parse the command line arguments, and set some global flags to
//    indicate what actions to perform
//
void ValidateArgs(int argc, char **argv)
{
    int i;

    for(i = 1; i < argc; i++)
    {
        if ((argv[i][0] == '-') || (argv[i][0] == '/'))
        {
            switch (tolower(argv[i][1]))
            {
                case 'p':        // Remote port
                    if (strlen(argv[i]) > 3)
                        iPort = atoi(&argv[i][3]);
                    break;
                case 'r':        // Recipient's IP addr
                    if (strlen(argv[i]) > 3)
                        strcpy(szRecipient, &argv[i][3]);
                    break;
                case 'c':        // Connect to recipients IP addr
                    bConnect = TRUE;
                    break;
                case 'n':        // Number of times to send message
                    if (strlen(argv[i]) > 3)
                        dwCount = atol(&argv[i][3]);
                    break;
                case 'b':        // Buffer size
                    if (strlen(argv[i]) > 3)
                        dwLength = atol(&argv[i][3]);
                    break;
                case 'd':        // Character to fill buffer
                    cChar = argv[i][3];
                    break;
                default:
                    usage();
                    break;
            }
        }
    }
}

//
// Function: main
//
// Description:
//    Main thread of execution. Initialize Winsock, parse the command
//    line arguments, create a socket, connect to the remote IP
//    address if specified, and then send datagram messages to the
//    recipient.
//
int main(int argc, char **argv)
{
    WSADATA        wsd;
    SOCKET         s;
    char          *sendbuf = NULL;
    int            ret,
                   i;
    SOCKADDR_IN    recipient;

    // Parse the command line and load Winsock
    //
    ValidateArgs(argc, argv);

    if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
    {
        printf("WSAStartup failed!\n");
        return 1;
    }
    // Create the socket
    //
    s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s == INVALID_SOCKET)
    {
        printf("socket() failed; %d\n", WSAGetLastError());
        return 1;
    }
    // Resolve the recipient's IP address or hostname
    //
    recipient.sin_family = AF_INET;
    recipient.sin_port = htons((short)iPort);
    if ((recipient.sin_addr.s_addr = inet_addr(szRecipient))
        == INADDR_NONE)
    {
        struct hostent *host=NULL;

        host = gethostbyname(szRecipient);
        if (host)
            CopyMemory(&recipient.sin_addr, host->h_addr_list[0],
                host->h_length);
        else
        {
            printf("gethostbyname() failed: %d\n", WSAGetLastError());
            WSACleanup();
            return 1;
        }
    }
    // Allocate the send buffer
    //
    sendbuf = GlobalAlloc(GMEM_FIXED, dwLength);
    if (!sendbuf)
    {
        printf("GlobalAlloc() failed: %d\n", GetLastError());
        return 1;
    }
    memset(sendbuf, cChar, dwLength);
    //
    // If the connect option is set, "connect" to the recipient
    // and send the data with the send() function
    //
    if (bConnect)
    {
        if (connect(s, (SOCKADDR *)&recipient, 
                sizeof(recipient)) == SOCKET_ERROR)
        {
            printf("connect() failed: %d\n", WSAGetLastError());
            GlobalFree(sendbuf);
            WSACleanup();
            return 1;
        }
        for(i = 0; i < dwCount; i++)
        {
            ret = send(s, sendbuf, dwLength, 0);
            if (ret == SOCKET_ERROR)
            {
                printf("send() failed: %d\n", WSAGetLastError());
                break;
            }
            else if (ret == 0)
                break;
            // send() succeeded!
        }
    }
    else
    {
        // Otherwise, use the sendto() function
        //
        for(i = 0; i < dwCount; i++)
        {
            ret = sendto(s, sendbuf, dwLength, 0, 
                    (SOCKADDR *)&recipient, sizeof(recipient));
            if (ret == SOCKET_ERROR)
            {
                printf("sendto() failed; %d\n", WSAGetLastError());
                break;
            }
            else if (ret == 0)
                break;
            // sendto() succeeded!
        }
    }
    closesocket(s);

    GlobalFree(sendbuf);
    WSACleanup();
    return 0;
}
/************************* End of Sender ***********************/
/************************************************************/
/************************** Receiver *************************/
// Module Name: Receiver.c
//
// Description:
//    This sample receives UDP datagrams by binding to the specified
//    interface and port number and then blocking on a recvfrom() 
//    call
//
// Compile:
//    cl -o Receiver Receiver.c ws2_32.lib
//
// Command line options:
//    sender [-p:int] [-i:IP][-n:x] [-b:x]
//           -p:int   Local port
//           -i:IP    Local IP address to listen on
//           -n:x     Number of times to send message
//           -b:x     Size of buffer to send
//
#include <winsock2.h>
#include <stdio.h>
#include <stdlib.h>

#define DEFAULT_PORT            5150
#define DEFAULT_COUNT           25
#define DEFAULT_BUFFER_LENGTH   4096

int   iPort    = DEFAULT_PORT;          // Port to receive on
DWORD dwCount  = DEFAULT_COUNT,         // Number of messages to read
      dwLength = DEFAULT_BUFFER_LENGTH; // Length of receiving buffer
BOOL  bInterface = FALSE;               // Use an interface other than
                                        // default
char  szInterface[32];            // Interface to read datagrams from

//
// Function: usage:
//
// Description:
//    Print usage information and exit
//
void usage()
{
    printf("usage: sender [-p:int] [-i:IP][-n:x] [-b:x]\n\n");
    printf("       -p:int   Local port\n");
    printf("       -i:IP    Local IP address to listen on\n");
    printf("       -n:x     Number of times to send message\n");
    printf("       -b:x     Size of buffer to send\n\n");
    ExitProcess(1);
}

//
// Function: ValidateArgs
//
// Description:
//    Parse the command line arguments, and set some global flags to
//    indicate what actions to perform
//
void ValidateArgs(int argc, char **argv)
{
    int                i;

    for(i = 1; i < argc; i++)
    {
        if ((argv[i][0] == '-') || (argv[i][0] == '/'))
        {
            switch (tolower(argv[i][1]))
            {
                case 'p':   // Local port
                    if (strlen(argv[i]) > 3)
                        iPort = atoi(&argv[i][3]);
                    break;
                case 'n':   // Number of times to receive message
                    if (strlen(argv[i]) > 3)
                        dwCount = atol(&argv[i][3]);
                    break;
                case 'b':   // Buffer size
                    if (strlen(argv[i]) > 3)
                        dwLength = atol(&argv[i][3]);
                    break;
                case 'i':    // Interface to receive datagrams on
                    if (strlen(argv[i]) > 3)
                    {
                        bInterface = TRUE;
                    strcpy(szInterface, &argv[i][3]);
                    }
                    break;
                default:
                    usage();
                    break;
            }
        }
    }
}

//
// Function: main
//
// Description:
//    Main thread of execution. Initialize Winsock, parse the command
//    line arguments, create a socket, bind it to a local interface 
//    and port, and then read datagrams.
//
int main(int argc, char **argv)
{
    WSADATA        wsd;
    SOCKET         s;
    char          *recvbuf = NULL;
    int            ret,
                   i;
    DWORD          dwSenderSize;
    SOCKADDR_IN    sender,
                   local;

    // Parse arguments and load Winsock
    //
    ValidateArgs(argc, argv);

    if (WSAStartup(MAKEWORD(2,2), &wsd) != 0)
    {
        printf("WSAStartup failed!\n");
        return 1;
    }
    // Create the socket and bind it to a local interface and port
    //
    s = socket(AF_INET, SOCK_DGRAM, 0);
    if (s == INVALID_SOCKET)
    {
        printf("socket() failed; %d\n", WSAGetLastError());
        return 1;
    }
    local.sin_family = AF_INET;
    local.sin_port = htons((short)iPort);
    if (bInterface)
        local.sin_addr.s_addr = inet_addr(szInterface);
    else
        local.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(s, (SOCKADDR *)&local, sizeof(local)) == SOCKET_ERROR)
    {
        printf("bind() failed: %d\n", WSAGetLastError());
        return 1;
    }
    // Allocate the receive buffer
    //
    recvbuf = GlobalAlloc(GMEM_FIXED, dwLength);
    if (!recvbuf)
    {
        printf("GlobalAlloc() failed: %d\n", GetLastError());
        return 1;
    }
    // Read the datagrams
    //
    for(i = 0; i < dwCount; i++)
    {
        dwSenderSize = sizeof(sender);
        ret = recvfrom(s, recvbuf, dwLength, 0, 
                (SOCKADDR *)&sender, &dwSenderSize);
        if (ret == SOCKET_ERROR)
        {
            printf("recvfrom() failed; %d\n", WSAGetLastError());
            break;
        }
        else if (ret == 0)
            break;
        else
        {
            recvbuf[ret] = '\0';
            printf("[%s] sent me: '%s'\n", 
                inet_ntoa(sender.sin_addr), recvbuf);
        }
    }
    closesocket(s);

    GlobalFree(recvbuf);
    WSACleanup();
    return 0;
}
/************************* End of Receiver **********************/


Ну и посмотри ссылки тут.


--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
Karser
Дата 15.6.2007, 16:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.5.2007

Репутация: нет
Всего: нет



Спасибо, приложение кстати получилось одно))
еще вопрос про широковещательную отправку - нашел пример,
оформил его в виде флажка, но при отправке - запущенные приложения не получают мое сообщение совсем :(
может его принимать как то по особому надо? сниффер показывает, что ничего не отсылается, хотя sendto отрабатывает без ошибок..

Код

void __fastcall TForm1::cbClick(TObject *Sender)
{
  bool fBroadcast;
  if (cb->Checked){
    fBroadcast = TRUE;
  }else{
    fBroadcast = FALSE;
  }

  if (setsockopt (WinSocket, SOL_SOCKET, SO_BROADCAST, (CHAR *) &fBroadcast, sizeof ( BOOL )) != 0 ){
    Error_Mes = "Широковещание не работает: ";
    WSAErrorMessage(Error_Mes);
  }
}

а при отправке я меняю адрес отправителя на INADDR_BROADCAST
Код

  dest_sin.sin_addr.s_addr = INADDR_BROADCAST;//htonl ()

во вложении весь пример.

еще вопрос:
по дейтаграммам можно узнать список IP и DNS адресов компьютера в сети или мне нужно пересылать вручную эти данные?

Это сообщение отредактировал(а) Karser - 15.6.2007, 16:12

Присоединённый файл ( Кол-во скачиваний: 17 )
Присоединённый файл  ServEx.rar 5,57 Kb
PM MAIL   Вверх
ptr
Дата 19.6.2007, 06:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 661
Регистрация: 31.5.2006
Где: Новосибирск

Репутация: 9
Всего: 14



Цитата(Karser @  15.6.2007,  19:10 Найти цитируемый пост)
по дейтаграммам можно узнать список IP и DNS адресов компьютера в сети или мне нужно пересылать вручную эти данные?

Можно получить IP адрес отправителя. У recv/recvfrom один из параметров - указатель на sockaddr_in, в нем после приёма будет лежать информация об отправителе.


Цитата(Karser @  15.6.2007,  19:10 Найти цитируемый пост)
еще вопрос про широковещательную отправку - нашел пример,оформил его в виде флажка, но при отправке - запущенные приложения не получают мое сообщение совсем :(может его принимать как то по особому надо? сниффер показывает, что ничего не отсылается, хотя sendto отрабатывает без ошибок..

Для broadcast нет понятия IP адреса получателя. Вместо этого используются специальные broadcast адреса, например, 255.255.255.255. Приём broadcast делается как обычный приём, нет отличия broadcast или нет.




--------------------
Единственный способ определить границы возможного - это выйти за эти границы, в невозможное.
Артур Кларк.
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.1075 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.