Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Сокеты: широковещательное сообщение  (Прочитано 37239 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Sommer
Молодой специалист

us
Offline Offline

« : 16-09-2003 17:28 » 

кидаем в сеть сабж "кто сервер"
сервер отвечает "Я"
как реализовать?
как послать широковещательное сообщение?
Записан

когда-нибудь, я верю, ты будешь ехать по этому городу и поймёшь, что хочешь увидеть меня за рулём мчащейся по соседней полосе машины.
но тогда меня уже не будет
в этом городе
forever yours.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 16-09-2003 19:32 » 

Broadcast сокет:
Сокет UDP, bind на широковещательный адрес.

int n=1;
setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&n,sizeof(n));

Только это пример для *nix, а будет ли это работать на win... Надо пробовать.

Далее как обычный udp сокет.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Sommer
Молодой специалист

us
Offline Offline

« Ответ #2 : 17-09-2003 04:18 » 

RXL, нельзя через TCP сокет?
Записан

когда-нибудь, я верю, ты будешь ехать по этому городу и поймёшь, что хочешь увидеть меня за рулём мчащейся по соседней полосе машины.
но тогда меня уже не будет
в этом городе
forever yours.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #3 : 17-09-2003 08:38 » 

Нет - broadcast может быть только SOCK_DGRAM !
Поток же (SOCK_STREAM) возможен только между двумя точками. И при попытке включить SO_BROADCAST, setsockopt() вернет ошибку.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Sommer
Молодой специалист

us
Offline Offline

« Ответ #4 : 04-10-2003 21:14 » 

Цитата: RXL
Broadcast сокет:
Сокет UDP, bind на широковещательный адрес.

int n=1;
setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&n,sizeof(n));

Только это пример для *nix, а будет ли это работать на win... Надо пробовать.

Далее как обычный udp сокет.

bind на широковещательный адрес делается так?:
Код:
    sockaddr_in local_addr;
    local_addr.sin_family=AF_INET;
    local_addr.sin_addr.s_addr=INADDR_ANY;
    local_addr.sin_port=htons(PORT);
    if (bind(my_sock,(sockaddr *) &local_addr, sizeof(local_addr))) {
        printf("bind error: %d\n",WSAGetLastError());
        closesocket(my_sock);
        WSACleanup();
        return -1;
    }
n - указатель на буфер возвращаемых значений?

делаем setsockopt(...)
а что потом? recvfrom()?
« Последнее редактирование: 19-11-2007 19:46 от Алексей1153++ » Записан

когда-нибудь, я верю, ты будешь ехать по этому городу и поймёшь, что хочешь увидеть меня за рулём мчащейся по соседней полосе машины.
но тогда меня уже не будет
в этом городе
forever yours.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 05-10-2003 13:54 » 

mandela, здесь я ошибся.
bind() делается на свой собственный адрес. Можно его не делать и адрес и порт назначатся автоматически при первой же отсылке, но обычно bc-сервисы используют определенный порт.
Можно назначить и INADDR_ANY, но лучше определенный адрес с определенного интерфейса.

Пример:

Код:
/* маска сети 255.255.255.0 */

char *buf="aaaaaaa";
int bufsz=7;

int sock,len;
struct sockaddr_in sa;

sock=socket(PF_INET,SO_DGRAM,0);
sa.sin_family=AF_INET;
sa.sin_addr.s_addr=htonl(0x0a000001); /* 10.0.0.1 */
sa.sin_port=htons(137); /* ;) */
bind(sock,(struct sockaddr*)&sa,sizeof(sa)); /* закрепляем за сокетом местный адрес+порт */
len=1;
setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&len,sizeof(len)); /* включаем bc - делать это обязательно, т.к. ethernet пакеты тоже должны быть bc*/
sa.sin_addr.s_addr=htonl(0x0a0000ff); /* 10.0.0.255 */
len=sizeof(sa);
sendto(sock,buf,bufsz,0,(struct sockaddr*)&sa,len); /* этот пакет получат все хосты в сети 10.0.0.0/24 */
« Последнее редактирование: 19-11-2007 19:48 от Алексей1153++ » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Sommer
Молодой специалист

us
Offline Offline

« Ответ #6 : 05-10-2003 17:47 » 

RXL,
спасибо за пример )
Записан

когда-нибудь, я верю, ты будешь ехать по этому городу и поймёшь, что хочешь увидеть меня за рулём мчащейся по соседней полосе машины.
но тогда меня уже не будет
в этом городе
forever yours.
Sommer
Молодой специалист

us
Offline Offline

« Ответ #7 : 05-10-2003 19:35 » 

гм... чего-то у меня не получается..
есть демон-сервер, который отсылает обратно все, что ему приходит:
Код:
#include "stdafx.h"
#include <stdio.h>
#include <winsock2.h>
#define PORT 666 // ???? ???????
#define sHELLO "Hello, %s [%s] Sailor\n"
int main(int argc, char* argv[]) {

    char buff[1024];
    printf("UDP DEMO echo-Server\n");


    // ??????????? ??????????
    if (WSAStartup(0x202,(WSADATA *) &buff[0])) {
        printf("WSAStartup error: %d\n",WSAGetLastError());
        return -1;
    }

    // ???????? ??????
    SOCKET my_sock;
    my_sock=socket(AF_INET,SOCK_DGRAM,0);
    if (my_sock==INVALID_SOCKET) {
        printf("Socket() error: %d\n",WSAGetLastError());
        WSACleanup();
        return -1;   
    }


    // ?????????? ?????? ? ????????? ???????
    sockaddr_in local_addr;
    local_addr.sin_family=AF_INET;
    local_addr.sin_addr.s_addr=INADDR_ANY;
    local_addr.sin_port=htons(PORT);
    if (bind(my_sock,(sockaddr *) &local_addr, sizeof(local_addr))) {
        printf("bind error: %d\n",WSAGetLastError());
        closesocket(my_sock);
        WSACleanup();
        return -1;
    }

   
    setsockopt(my_sock,SOL_SOCKET,SO_BROADCAST,&buff[0],sizeof(buff)-1);



    // ????????? ???????, ?????????? ?????????
    while(1) {

        sockaddr_in client_addr;
        int client_addr_size = sizeof(client_addr);
        int bsize=recvfrom(my_sock,&buff[0],sizeof(buff)-1,0,
        (sockaddr *) &client_addr, &client_addr_size);

        if (bsize==SOCKET_ERROR) {
            printf("recvfrom() error: %d\n",WSAGetLastError());
        }

        // ?????????? IP-????? ??????? ? ?????? ????????
        HOSTENT *hst;

        hst=gethostbyaddr((char *) &client_addr.sin_addr,4,AF_INET);
        printf("+%s [%s:%d] new DATAGRAM!\n",
            (hst)?hst->h_name:"Unknown host",
            inet_ntoa(client_addr.sin_addr),
            ntohs(client_addr.sin_port));

        // ????????? ??????????? ????
        buff[bsize]=0;

        // ????? ?? ?????
        printf("C=>S:%s\n",&buff[0]);

        // ??????? ?????????? ???????
        sendto(my_sock,&buff[0],bsize,0,
        (sockaddr *)&client_addr, sizeof(client_addr));
    }

    return 1;
}

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

так же я создал еще один поток, в котором хочу рассылать широковещательные сообщения, получать их од демона и печатать.
но демон их не принимает...
наверное они не отсылаются?...
Код:
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include "functions.h"
#define PORT 666
#define SERVERADDR "127.0.0.1"
int main(int argc, char* argv[]) {
    char buff[10*1014];
    printf("UDP DEMO Client\nType quit to quit\n");

    // ???????????? ?????????? Winsocks
    if (WSAStartup(0x202,(WSADATA *)&buff[0])) {
    printf("WSAStartup error: %d\n",WSAGetLastError());
    return -1;
    }

    // ???????? ??????
    SOCKET my_sock=socket(AF_INET, SOCK_DGRAM, 0);
    if (my_sock==INVALID_SOCKET) {
    printf("socket() error: %d\n",WSAGetLastError());
    WSACleanup();
    return -1;
    }


    //????? ????????? ? ????????
    HOSTENT *hst;
    sockaddr_in dest_addr;
    dest_addr.sin_family=AF_INET;
    dest_addr.sin_port=htons(PORT);

    // ??????????? IP-?????? ????
    if (inet_addr(SERVERADDR)) {
        dest_addr.sin_addr.s_addr=inet_addr(SERVERADDR);
    { else {

        if (hst=gethostbyname(SERVERADDR)) {
            dest_addr.sin_addr.s_addr=((unsigned long **) hst->h_addr_list)[0][0];
        { else {

            printf("Unknown host: %d\n",WSAGetLastError());
            closesocket(my_sock);
            WSACleanup();
            return -1;
        }
    }
   
    struct ch1 data_ch1;
    data_ch1.my_sock = &my_sock;
    data_ch1.dest_addr = dest_addr;

    //////////////////
   
    SOCKET sock;
    char *buf="aaaaaaa";
    int bufsz=7;
    char len;
    struct sockaddr_in sa;
    sock=socket(PF_INET,SOCK_DGRAM,0);
    sa.sin_family=AF_INET;
    //sa.sin_addr.s_addr=htonl(0x0a000001); /* 10.0.0.1 */     
    sa.sin_addr.s_addr=inet_addr(SERVERADDR);
    sa.sin_port=htons(137); /* ;) */
    bind(sock,(struct sockaddr*)&sa,sizeof(sa)); /* ?????????? ?? ??????? ??????? ?????+???? */
    len=1;
    setsockopt(sock,SOL_SOCKET,SO_BROADCAST,&len,sizeof(len)); /* ???????? bc - ?????? ??? ???????????, ?.?. ethernet ?????? ???? ?????? ???? bc*/
    //sa.sin_addr.s_addr=htonl(0x0a0000ff); /* 10.0.0.255 */
    sa.sin_addr.s_addr=inet_addr("127.0.0.255");
    len=sizeof(sa);
//    sendto(sock,buf,bufsz,0,(struct sockaddr*)&sa,sizeof(sa)); /* ???? ????? ??????? ??? ????? ? ???? 10.0.0.0/24 */

    struct ch1 dataDemon;
    dataDemon.my_sock = &sock;
    dataDemon.dest_addr = sa;

    //////////////////

    HANDLE hThreads[3];
    unsigned uThreadIDs[3];
   

    hThreads[1] = (HANDLE) _beginthreadex(NULL,0,sendData, &data_ch1,0,&uThreadIDs[1]);

    hThreads[2] = (HANDLE) _beginthreadex(NULL,0,receiveData, &my_sock,0,&uThreadIDs[2]);
   
   
    hThreads[0] = (HANDLE) _beginthreadex(NULL,0,runDemon, &dataDemon,0,&uThreadIDs[0]);

   


    WaitForMultipleObjects(3, hThreads, TRUE, INFINITE );

    CloseHandle( hThreads[0] );
    CloseHandle( hThreads[1] );   
    CloseHandle( hThreads[2] ); 

    // ??? ????????? - ?????
    closesocket(my_sock);
    closesocket(sock);
    WSACleanup();
    return 0;
}


функции :
Код:
unsigned __stdcall receiveData (void * arg) {
    SOCKET * my_sock = (SOCKET *)arg;
    // ????? ????????? ? ???????
    char buff[10*1014];
    sockaddr_in server_addr;
    int server_addr_size=sizeof(server_addr);
    int n;

    sockaddr_in client_addr;
    int client_addr_size = sizeof(client_addr);
   
    HOSTENT *hst;

    while(1) {       
        n=recvfrom(*my_sock,&buff[0],sizeof(buff)-1,0,
            (sockaddr *) &server_addr, &server_addr_size);
/*        if (n==SOCKET_ERROR) {
            printf("recvfrom() error: %d\n",WSAGetLastError());
            closesocket(*my_sock);
            WSACleanup();
            break;
        }
*/     
        if (n != SOCKET_ERROR) {
            buff[n]=0;
            // ????? ????????? ? ??????? ????????? ?? ?????
            printf("S=>C:%s",&buff[0]);

           
        }
    }
    _endthreadex( 0 );
    return 0;
}

unsigned __stdcall sendData(void * arg) {
    ch1 * data_ch1 = (ch1*)arg;
    while(1) {
        char buff[10*1014];
        // ?????? ????????? ? ??????????
        printf("S<=C:");fgets(&buff[0],sizeof(buff)-1,stdin);
        if (!strcmp(&buff[0],"quit\n")) {
            _endthreadex( 0 );
            return 0;
        }

        // ???????? ????????? ?? ??????
        sendto(*(data_ch1->my_sock), &buff[0], strlen(&buff[0]), 0,
            (sockaddr *) &(data_ch1->dest_addr), sizeof(data_ch1->dest_addr));
    }
    _endthreadex( 0 );
    return 0;
}

unsigned __stdcall runDemon(void * arg) {
    ch1 * data_ch1 = (ch1*)arg;
    char *buf="aaaaaaa";
    int bufsz=7;
    while(1) {
        sendto(*(data_ch1->my_sock),buf,bufsz,0,
            (sockaddr *) &(data_ch1->dest_addr), sizeof(data_ch1->dest_addr));
        //delay(3000);
    }
    _endthreadex( 0 );
    return 0;
}
и
Код:
struct ch1 {
    SOCKET * my_sock;
    sockaddr_in dest_addr;
};
вот...
я все же думаю, что я неправильно рассылаю широковещательные сообщения....
не так?..
p.s. я все это пытаюсь тестиить через localhost
« Последнее редактирование: 19-11-2007 19:52 от Алексей1153++ » Записан

когда-нибудь, я верю, ты будешь ехать по этому городу и поймёшь, что хочешь увидеть меня за рулём мчащейся по соседней полосе машины.
но тогда меня уже не будет
в этом городе
forever yours.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 06-10-2003 06:39 » 

Не все интерфейсы поддерживают широковещательную передачу. Напр. ppp и локальная петля (127.0.0.1) ее не поддерживают - в принципе не могут! Проверяй ошибки sendto() - должна система что-нибудь нехорошее при этом сказать.
Код пока не читал - там могут быть еще ошибки.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Sommer
Молодой специалист

us
Offline Offline

« Ответ #9 : 07-10-2003 19:58 » 

RXL, а если без setsockopt
сделать sendTo на N.N.N.255 ? где первые 3 N - номер нашей сети?...
не получится?...
Записан

когда-нибудь, я верю, ты будешь ехать по этому городу и поймёшь, что хочешь увидеть меня за рулём мчащейся по соседней полосе машины.
но тогда меня уже не будет
в этом городе
forever yours.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 07-10-2003 21:00 » 

Ошибка
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines