Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Не доходяд UDP пакеты, самому себе 
:(
    Опции темы
Sharkfire
Дата 6.11.2007, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Написал класс TMyUDP:

Его Код:
Код

#pragma hdrstop

#include "TMyUDP.h"
#include <stdio.h>
#include <math.h>
#include <winsock2.h>
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
TMyUDP::TMyUDP()
{
 this->LocalPort=0;
 this->RemotePort=0;
 this->RemoteHost=new char[100];
 this->Ready=0;
 WSADATA socdate;
 if(!(WSAStartup(MAKEWORD(2,0),&socdate)>0))
 Ready=1;
 this->BytesSent=0;
 this->BytesReseived=0;
 }
//---------------------------------------------------------------------------
void TMyUDP::Open(int LPort)
{
if ((WinSocket = socket (AF_INET, SOCK_DGRAM,IPPROTO_UDP)) != INVALID_SOCKET)
{
    if(WSAAsyncSelect(WinSocket,NULL,WM_SOCKET,FD_READ|FD_WRITE|FD_ACCEPT|FD_CONNECT|FD_CLOSE) != SOCKET_ERROR)
    {
      SOCKADDR_IN local_sin;
      local_sin.sin_family = AF_INET;
      local_sin.sin_port = htons(LPort);
      local_sin.sin_addr.s_addr = htonl (INADDR_ANY);
      if (bind (WinSocket, (struct sockaddr *) &local_sin, sizeof (local_sin)) != SOCKET_ERROR)
      {
      this->LocalPort=LPort;
      }
}
    }
}
//---------------------------------------------------------------------------
void TMyUDP::Socket_Message(TMessage &Message)
{
switch(Message.LParamLo)
  {    case FD_READ:{
      char szMessageA [100];
      TCHAR szMessageW [100];
      int iRecvLen , index;
      SOCKADDR_IN recv_sin;
      iRecvLen = sizeof (recv_sin);

if(recvfrom (WinSocket,szMessageA,sizeof(szMessageA),0,(struct sockaddr *) &recv_sin, &iRecvLen) != SOCKET_ERROR)
      {
        // Convert the ASCII string to Unicode.
        for (index = 0; index <= sizeof (szMessageA); index++)
        szMessageW [index] = szMessageA[index];
        if(OnReseive)
         OnReseive(szMessageW,iRecvLen);
         this->BytesReseived+=iRecvLen;
      }
      break;
    }
    }
}
//---------------------------------------------------------------------------
void TMyUDP::Close()
{
 shutdown (WinSocket, 0x00); // Блокировка приема (reciving) на

 if (closesocket (WinSocket)!=SOCKET_ERROR)
  this->Ready=0;
}
//---------------------------------------------------------------------------
void TMyUDP::SendBuf(char * buf,int buflen)
{
 SOCKADDR_IN dest_sin;
  dest_sin.sin_family = AF_INET;
  dest_sin.sin_port = htons (LocalPort);
    HOSTENT *hst;
    if (inet_addr(RemoteHost)!=INADDR_NONE)
      dest_sin.sin_addr.s_addr=inet_addr(RemoteHost);
    else
      if (hst==gethostbyname(RemoteHost))
        ((unsigned long *)&dest_sin.sin_addr)[0]= ((unsigned long **)hst->h_addr_list)[0][0];
  if (sendto (WinSocket,buf,strlen (buf) + 1, 0, (struct sockaddr FAR *) &dest_sin, sizeof (dest_sin)) != SOCKET_ERROR) {
this->BytesSent+=buflen;
}
  }
//---------------------------------------------------------------------------
TMyUDP:: ~TMyUDP()
{
WSACleanup();
}
//---------------------------------------------------------------------------


Его ХЄД:
Код

//---------------------------------------------------------------------------
#ifndef TMyUDPH
#define TMyUDPH
#define WM_SOCKET WM_USER+400
//---------------------------------------------------------------------------
#endif

#include <windows.h>
#include <Messages.hpp>
class TMyUDP
 {
public:
 TMyUDP();
~TMyUDP();
 int RemotePort;
 char *RemoteHost;
 void Open(int Port);
 void SendBuf(char * buf,int buflen);
 int BytesSent;
 int BytesReseived;
 typedef bool (__fastcall * MyUDP_ReseiveF )(char *Buf,int BufLen);
 MyUDP_ReseiveF OnReseive;
 void Close();
  BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_SOCKET,TMessage,Socket_Message)
  END_MESSAGE_MAP(TMyUDP)
 //String toString();
private:
 void Socket_Message(TMessage &Message);
 bool Ready;
 int LocalPort;
 int WinSocket;
 };


Использую класс так:

Код

#include <vcl.h>
#pragma hdrstop

#include "u1.h"
#include <TMyUDP.h>

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm6 *Form6;
TMyUDP *In;
TMyUDP *Out;
bool __fastcall Res(char *Buf,int BufLen);
//---------------------------------------------------------------------------
__fastcall TForm6::TForm6(TComponent* Owner)
    : TForm(Owner)
{

}
//---------------------------------------------------------------------------
bool __fastcall Res(char *Buf,int BufLen)
{
ShowMessage(Buf);
}
//---------------------------------------------------------------------------
void __fastcall TForm6::Button1Click(TObject *Sender)
{
In = new TMyUDP();
Out= new TMyUDP();
int inPort=56790;
int outPort=56789;
In-> Open(inPort);
Out->Open(outPort);
Out->RemotePort=inPort;
Out->RemoteHost="127.0.0.1";
In->OnReseive=Res;
}
//---------------------------------------------------------------------------

void __fastcall TForm6::Button2Click(TObject *Sender)
{
Out->SendBuf("BUFFER.",7);    
}
//---------------------------------------------------------------------------


100% что в момент испытания мой айпи 127.0.0.1
но пакеты не доходяд, или доходяд? но я об этом не знаю!!!

В чём трабла, помогите плиз!!!!??
PM MAIL ICQ   Вверх
Олег2005
Дата 7.11.2007, 10:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

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



Не уловил общей концепции, но трабла по моему именно здесь:
WSAAsyncSelect(WinSocket,NULL,WM_SOCKET,FD_READ|FD_WRITE|FD_ACCEPT|FD_CONNECT|FD_CLOSE)
1. WSAAsyncSelect() автоматически переводит сокет в неблокирующий режим, и дальнейшие действия с сокетом должны это учитывать
2.Что делает  WSAAsyncSelect(WinSocket,NULL,WM_SOCKET.............)? Она указывает, какому окну посылать данное сообщение при наступлении перечисленных сетевых событий. У вас этот параметр - hWnd окна равен NULL - те посылает в никуда
3.Событий  |FD_ACCEPT|FD_CONNECT|FD_CLOSE в UDP нет - это из TCP - там есть только FD_READ|FD_WRITE
4. Если всетаки хочется ее использовать, то в консольном безоконном приложении создается скрытое Windows-окно, кому и посылается сообщение.
5. Лучше всего в вашем случае использовать проcтую функцию select() c  бесконечным таймаутом, те ждем пока чтото не прийдет
PM MAIL WWW MSN   Вверх
GrayCardinal
Дата 7.11.2007, 11:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Фигасе
****


Профиль
Группа: Завсегдатай
Сообщений: 3039
Регистрация: 9.11.2003

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



Олег2005, 
ой какая муть. извините, не сдержался  smile 


--------------------
PM MAIL WWW   Вверх
mrbrooks
Дата 7.11.2007, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

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



Как ща помню UDP такой протокол который и не дает гарантии что данные дойдут smile 
Но это лирика. 
Попробуй просто написать клиента и посмотри какие данные приходят и приходят ли вообще.

Это сообщение отредактировал(а) mrbrooks - 7.11.2007, 12:32
PM MAIL   Вверх
Олег2005
Дата 7.11.2007, 12:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

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



Цитата(GrayCardinal @  7.11.2007,  11:12 Найти цитируемый пост)
ой какая муть. извините, не сдержался 

Ну что ж, давайте по пунктам:
1.2 MSDN
Цитата

The WSAAsyncSelect function requests Windows message-based notification of network events for a socket.
int WSAAsyncSelect(
  __in          SOCKET s,
  __in          HWND hWnd,
  __in          unsigned int wMsg,
  __in          long lEvent
);
Parameters
s    A descriptor that identifies the socket for which event notification is required.
hWnd    A handle that identifies the window that will receive a message when a network event occurs.
wMsg    A message to be received when a network event occurs.
lEvent    A bitmask that specifies a combination of network events in which the application is interested.

Теперь пункт 3
Из http://groups.google.com/group/microsoft.public.vc.language/
Цитата

You will never receive FD_CLOSE notification on a UDP socket. FD_CLOSE
notifies a TCP socket that the connection is terminated by remote peer.
UDP socket does not maintain a connection nor does it have a permanent
remote peer.-- 
With best wishes,
    Igor Tandetnik 

FD_CONNECT - вы его можете получить только в случвае прибитого сокета, на котором выполнился connect вместо bind - но в как раз сокет биндите а не коннектите
Все дальнейшее - очевидно
Так что жду ваших комментариев - може вы гуру почище Стивенса???
PS1
Может я и не так силен в объектно-ориентированном программировании, но курс сетевого программирования я читаю уже лет 10 - и уж кое-что там знаю smile 
А семь моделей сетевого I/O в Виндах, включая и I/O Completion Port - знаю назубок smile 
PS2
Хотя..... вдруг вы что-то новое открыли?
Не жадничайте, расскажите - я учусь с удовольствием smile 

Это сообщение отредактировал(а) Олег2005 - 7.11.2007, 13:10
PM MAIL WWW MSN   Вверх
xvr
Дата 7.11.2007, 16:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Жуть!

Код

if(WSAAsyncSelect(WinSocket,NULL,WM_SOCKET,FD_READ|FD_WRITE|FD_ACCEPT|FD_CONNECT|FD_CLOSE) != SOCKET_ERROR)
Про WSAAsyncSelect вам тут уже подробно расказали.
Код

if(recvfrom (WinSocket,szMessageA,sizeof(szMessageA),0,(struct sockaddr *) &recv_sin, &iRecvLen) != SOCKET_ERROR)
      {
        // Convert the ASCII string to Unicode.
        for (index = 0; index <= sizeof (szMessageA); index++)
        szMessageW [index] = szMessageA[index];
Получили сообщение (представим себе, что получили smile ), проигнорировали его длинну и обработали весь буфер (за что его так?) Кроме того, если вы думаете, что просто откопировав ASCII символ в Unicode вы его таким образом преобразуете - вы заблуждаетесь.
Код

HOSTENT *hst;
    if (inet_addr(RemoteHost)!=INADDR_NONE)
      dest_sin.sin_addr.s_addr=inet_addr(RemoteHost);
    else
      if (hst==gethostbyname(RemoteHost))
        ((unsigned long *)&dest_sin.sin_addr)[0]= ((unsigned long **)hst->h_addr_list)[0][0];
Внимательно посмотрите во второй if - сдается мне, что вы хотели там написать '=' а не '=='

И собственно почему все не работает:
Код

class TMyUDP
 {
  BEGIN_MESSAGE_MAP
    MESSAGE_HANDLER(WM_SOCKET,TMessage,Socket_Message)
  END_MESSAGE_MAP(TMyUDP)
 }
Кто (и с какого перепугу) сказал вам, что BEGIN_MESSAGE_MAP/END_MESSAGE_MAP будет работать не то что в не оконном, а даже вообще не в VCL классе? (Не говоря уже про сообщение WM_SOCKET - MSDN такого не знает, я тоже)


Это сообщение отредактировал(а) xvr - 7.11.2007, 16:51
PM MAIL   Вверх
Sharkfire
Дата 7.11.2007, 16:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



 smile 

Так а чо мне делать то??
Вы тут так красиво раскритиковали мой код (кстате все материалы для него взяты с форума єтого)
а что надо конкретно исправить не сказазли???!!  smile 

Кулас будет использоватся тольком моей программой и тольков среде C++ Builder 2006  smile 


Это сообщение отредактировал(а) Sharkfire - 7.11.2007, 16:39
PM MAIL ICQ   Вверх
Олег2005
Дата 7.11.2007, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

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



Цитата(Sharkfire @  7.11.2007,  16:34 Найти цитируемый пост)
А что за функция Select, и что за таймут..!!  я в сетвом WinApi чайник.... !! 

Ну вот это уже ближе к истине:
Цитата

2.5.7.    Функция select()
Существует еще одна функция, которая часто используется многими клиентскими и серверными программами и называется "select()". Функция select() позволяет одиночному процессу следить за состоянием сразу нескольких сокетов – это для *nix-систем. Прототип select():
int select(int number_of_sockets, fd_set *readable_sockets, fd_set *writeable_sockets, fd_set *error_sockets, struct timeval *timeout); 
При вызове select() указываются пять параметров. Первый параметр, количество сокетов (number_of_sockets), задает общее количество сокетов для наблюдения (в некоторых реализациях не используется и является необязательным, по умолчанию это число не должно превышать 64). 
Параметры readable_sockets, writeable_sockets и error_sockets являются специальными битовыми масками типа fd_set, задающими вид наблюдаемых сокетов. 
Сокет для чтения (readable_socket) готов принять данные, которые извлекаются программой при помощи стандартных вызовов recv() или recvfrom(). 
Сокет, готовый для записи (writable_socket) — это сокет, установивший соединение. Через него программа может передавать данные, используя стандартные функции типа send() или sendto(). 
В случае сетевой ошибки функция select() помечает сокет, в котором это произошло, как ошибочный (exception) – error_sockets. Ситуация ошибки требует дальнейшей программной обработки. 
Значение number_of_sockets должно быть на 1 больше номера самого наибольшего сокетного дескриптора, используемого в вызове – так как в UNIX счет дескрипторов ведется с нуля.
Примечание:
В Windows-системах из-за разной трактовки понятия сокетного дескриптора number_of_sockets  может быть указан и равным 0.
Для указания таймаута в вызове select(), применяется структура timeval с двумя полями:
struct timeval 
{
        int tv_sec;     /* секунды */
        int tv_usec;    /* микросекунды */
};
Хотя второе поле структуры предполагает задание времени в микросекундах, стандартный UNIX- интервал – 100 миллисекунд, и поэтому устанавливать меньшее значение нецелесообразно. 
Если установить все поля в структуре timeval в 0, select() сработает по timeout немедленно, опросив до этого все наборы дескрипторов файлов. 
Если установить параметр timeout в NULL, то событие timeout не произойдет никогда и программа будет ожидать, пока какой-либо дескриптор файла не будет готов первым, т.е. если не важно время ожидания события в конкретном наборе.
Приведенный ниже вызов демонстрирует обращение к функции select():
res = select (number_of_sockets, readable_sockets, writeable_sockets, error_sockets, timeout); 
В качестве результата функция возвращает:
·    res – целое >0 – количество "готовых" сокетов;
·    res = -1 при ошибке (например, исполнение функции было прервано каким-либо сигналом;)
·    res = 0 если функция вернула управление до возникновения события в каком-либо сокете.
 Пусть, например, приложение посылает системный вызов recvfrom(). Вызов поступает в ядро, и:
·    если датаграмма уже пришла и находится в буфере ядра (в компоненте ядра), то вызов recvfrom() завершается нормально копированием полученных из сети данных в буфер приложения (в компоненту приложения);
·    если датаграмма еще не пришла в компоненту ядра, то вызов recvfrom() блокирует дальнейшее исполнение программы приложения на все время ожидания приема данных из сети. Лишь по приходу данных происходит их копирование в компоненту приложения и нормальное завершение системного вызова recvfrom().
Сокет, как программная абстракция, является "собственностью" ядра системы. Поэтому все возникающие в нем ситуации и события в первую очередь контролирует ядро системы. Реализация select() в ядре предполагает отслеживание ядром некоторых событий, связанных с заданными наборами сокетов, и установку битов в соответствующих наборах дескрипторов, которые задаются до вызова select(). Для заданных дескрипторов файлов функция select() также изменяет их битовые маски.
В любом случае select() определяет состояние только тех сокетов, которые были отмечены в каждой битовой маске. При выходе в вызывающую программу select() значение res возвращает количество сокетов, готовых к операциям ввода-вывода или зафиксировавших ошибку. 
Другими словами, функции select() указывается, за какими сокетами следить и какого рода информация о каждом из сокетов нас интересует. Функция select(), в свою очередь, информирует о количестве сокетов, готовых для приема-передачи данных. Если бит, идентифицирующий определенный сокет, окажется установленным, это значит, что сокет готов к операции ввода-вывода (чтению, записи или сообщению об ошибке). В дополнение select() модифицирует битовые маски таким образом, что каждый сокет оказывается принадлежащим определенной категории. 
До того как вызвать функцию select(), программа должна установить биты в маске так, чтобы они указывали на сокеты, информацию о которых необходимо получить. Функция select() после своего завершения сбросит биты, указывающие на любой сокет, не готовый к определенной операции ввода-вывода. После завершения функции select() прикладная программа может проанализировать содержимое битовой маски. 
Используя это свойство функции select(), можно написать программу так, что она будет изменять свое выполнение в зависимости от результатов вызова. Пусть у нас есть программа, создающая три сокета. Предположим, у нас есть одна процедура, обслуживающая операции чтения, другая процедура, осуществляющая запись, и третья, обрабатывающая ошибочные ситуации. Функция select() может вызываться, чтобы одновременно получить информацию о состоянии сокетов всех трех видов, в результате чего программа может узнать, что один сокет может считывать данные, второй может записывать, а третий содержит информацию об ошибке. В этом случае, получив статус всех контролируемых сокетов, разумнее всего будет прежде вызвать процедуру обработки ошибок. 
Каждый набор сокетов – это фактически структура, содержащая массив long integer битовых масок; размер массива установлен определением константы FD_SETSIZE.
Применение select() часто называют "мультиплексированием ввода/вывода". Почему? Особенностью этой функции является то, что она может отслеживать состояние множества (мульти) самых разных файловых и сокетных дескрипторов одновременно и затем дать программе возможность продолжить работу с одним избранным дескриптором.
1. Сокет готов для чтения, если выполнено одно из следующих условий:
·    Число байтов данных в приемном буфере сокета больше или равно текущему значению минимального количества данных low water-mark (может быть задано функцией setsockopt() с помощью опции сокета SO_RCVLOWAT, см. 2.9.1) для приемного буфера сокета. Для сокетов TCP и UDP значение low water-mark по умолчанию равно 1. Текущая операция чтения данных из сокета не блокирует исполнение и возвратит значение, большее нуля (то есть данные, которые были готовые для чтения). 
·    На противоположном конце партнер закрывает TCP-соединение (получен сегмент FIN). Операция считывания данных из сокета не блокируется и возвратит нуль (то есть признак конца файла).
·    Сокет является прослушивающим (TCP), и число установленных соединений ненулевое.
·    Ошибка сокета, ожидающая обработки. Операция чтения на сокете не блокируется и возвратит ошибку (-1) со значением переменной еrrnо c конкретным условием ошибки. Ошибки, ожидающие обработки, можно также получить, вызвав функцию getsockopt() с параметром SO_ERROR (см. 2.9.2), после чего состояние ошибки будет сброшено.
2. Сокет готов для записи, если выполнено одно из следующих условий:
·    Количество байтов доступного пространства в буфере отправки сокета больше или равно текущему значению минимального количества данных для буфера отправки сокета и либо сокет является присоединенным, либо сокету не требуется соединения (UDP). Это значит, что если мы отключим блокировку для сокета, операция записи не заблокирует сокет и возвратит положительное значение (например, число байтов, принятых транспортным уровнем). Устанавливать минимальное количество отсылаемых данных можно с помощью параметра сокета SO_SNDLOWAT. По умолчанию это значение равно 2048 байт для сокетов TCP и UDP.
·    Получатель, которому отправляются данные, закрывает соединение. Операция записи в сокет сгенерирует сигнал SIGPIPE.
·    Ошибка сокета, ожидающая обработки. Операция записи в сокет не блокируется и возвратит ошибку (-1) со значением переменной еrrnо, указывающей на конкретное условие ошибки. Эти ошибки, ожидающие обработки, можно также получить и сбросить, вызвав функцию getsockopt() с параметром сокета SO_ERROR.
3. Исключительная ситуация, требующая обработки, может возникнуть на сокете в том случае, если приняты внеполосные (out-of-band) срочные данные либо если отметка внеполосных данных в принимаемом потоке еще не достигнута.
2.5.8.    Макрокоманды для работы с наборами сокетов
Как было сказано, программа должна установить биты в маске "слежения" за флагами файлов (файловых дескрипторов - fd). Для управления этими наборами декларируется специальный тип данных - тип fd_set. Следующие макрокоманды работают с этим типом: 
FD_ZERO (fd_set *set)    – очищает набор описателей файлов 
FD_SET (int fd, fd_set *set)    – добавляет fd к набору 
FD_CLR (int fd, fd_set *set)    – удаляет fd из набора 
FD_ISSET (int fd, fd_set *set)    – проверяет наличие зафиксированного события для fd
в   наборе 
Листинг 2.2 демонстрирует фрагмент кода, который "ждет" 2.5 секунды, чтобы "что-то" появилось в стандартном вводе STDIN (нажата хоть одна клавиша на клавиатуре): 
Листинг 2.2 Пример контроля операции ввода с клавиатуры
Код

#include <sys/time.h> 
#include <sys/types.h> 
#include <unistd.h> 
#define STDIN 0  /* дескриптор файла для стандартного ввода */
main ()
      {   struct timeval tv;
          fd_set readfds;
          tv.tv_sec = 2;
          tv.tv_usec = 500000;
          FD_ZERO(&readfds);
          FD_SET (STDIN, &readfds);
          /* Нас не интересуют writefds и errorfds */
          select (STDIN+1, &readfds, NULL, NULL, &tv); 
/*После нажатия клавиши клавиатуры нажать Enter*/
          if (FD_ISSET (STDIN, &readfds))
  printf (" Клавиша была нажата! \n ")
    else
  printf ("Timed out \n ");
     }

Параметр number_of_sockets в этом примере должен быть установлен в значение самого большого значения описателя файла плюс один, а именно он должен быть установлен в sockfd+1, чтобы быть всегда больше, чем значение дескриптора стандартного ввода STDIN, имеющего значение fd = 0 – как указывалось выше, это требование для Windows-систем необязательно, т.к. этот параметр игнорируется.
Следующий листинг 2.3 демонстрирует контроль за готовностью к чтению двух сокетов – sd1 и sd2:
Листинг 2.3 Пример контроля операции чтения из сокетов
Код

#include <sys/time.h>
#include <sys/types.h>
fd_set read_sd;
struct timeval wait;
int sd1,sd2,nb;
...
for (;;) 
{
      wait.tv_sec = 1; /* одна секунда */
      wait.tv_usec = 0;
      FD_ZERO(&read_sd);
      FD_SET(sd1, &read_sd);
      FD_SET(sd2, &read_sd);
      nb = select(FD_SETSIZE, &read_sd, (fd_set *) 0, (fd_set *) 0, &wait);
      if (nb <= 0) 
       { 
            printf ("select выполнилась с ошибкой, или select завершилась по timeout.\n");
       }
      if (FD_ISSET(sd1, &read_sd)) 
       { 
            printf ("Сокет №1 готов для считывания.\n ");
       }
      if (FD_ISSET(sd2, &read_sd)) 
       { 
            printf ("Сокет №2 готов для считывания.\n ");
}
}



Добавлено @ 16:52
Цитата(xvr @  7.11.2007,  16:31 Найти цитируемый пост)
Не говоря уже про сообщение WM_SOCKET - MSDN такого не знает, я тоже)

Он задал  пользовательское сообщение:
#define WM_SOCKET WM_USER+400
Обычно правда пишут 
#define WM_SOCKET WM_USER+1
Вот вам пример юниксовых клиент/сервер - переделайте и будет вам счастье
Код

#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <arpa/inet.h>  
#include <sys/types.h> 
#include <netinet/in.h> 
#include <netdb.h> 
#include <sys/socket.h> 
#define MYPORT 4950         /* Порт, на котором будут соединяться пользователи */
int main(int argc, char *argv[])
{
int sd;
struct sockaddr_in their_addr;    /* Информация о адресе сервера */
struct hostent *he;            /* he – указатель на структуру типа hostent */
int numbytes;
if (argc != 3) /*В командной строке указать имя программы, адрес сервера и сообщение */
{
fprintf(stderr, "usage: talker hostname message\n");
exit(1);
}
if ((he=gethostbyname(argv[1])) == NULL) /* Получить информацию о хосте-сервере */
{  
herror("gethostbyname");
exit(1);
}
if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 
{            /*Создаем UDP-сокет */
perror("socket");
exit(1);
}            /*Заполнение адресной структуры получателя (сервера) */
their_addr.sin_family = AF_INET;       /* Порядок байтов хоста */
their_addr.sin_port = htons(MYPORT);    /* short, сетевой порядок байтов */
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(their_addr.sin_zero), 8);      /* Запись нулей в остальную часть структуры */
if ((numbytes=sendto(sd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) 
{
perror("sendto");
exit(1);
    }
printf("sent %d bytes to %s\n",numbytes,inet_ntoa(their_addr.sin_addr));
close(sd);
return 0;
}
//Программа UDP-сервера
//Данная программа "слушает" сеть (точнее, ждет входящие пакеты на порту 4950.)
//Листинг 2.14 UNIX UDP-сервер
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <sys/socket.h> 
#define MYPORT 4950         /* Порт, на котором будут соединяться пользователи */
#define MAXBUFLEN 100
main()
{
int sd;
struct sockaddr_in my_addr;     /* Информация о локальном адресе */
struct sockaddr_in their_addr;    /* Структура, в которой разместится адресная информация отправителя (клиента) */
int addr_len, nb;
char buf[MAXBUFLEN];
if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) 
{
perror("socket");
exit(1);
}
        my_addr.sin_family = AF_INET;          /* Порядок байтов хоста */
        my_addr.sin_port = htons(MYPORT);      /* short, сетевой порядок байтов */
        my_addr.sin_addr.s_addr = INADDR_ANY;    /* Автозаполнение IP-адресом моего хоста */
        bzero(&(my_addr.sin_zero), 8);         /* Ноль в остальную часть структуры */
if (bind(sd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr))  == -1) 
        {
perror("bind");
exit(1);
        }
addr_len = sizeof(struct sockaddr);
/* Сокет не "слушает" сеть, а ждет заполнения буфера приема */
/* Именно recvfrom() возвращает нам указатель на структуру с адресом отправителя */
if ((nb=recvfrom(sd, buf, MAXBUFLEN, 0, (struct sockaddr *)&their_addr, &addr_len)) == -1) 
{
perror("recvfrom");
exit(1);
}        /* От кого получили */
printf("Got packet from %s\n",inet_ntoa(their_addr.sin_addr));
printf("Packet is %d bytes long\n",nb);    /* Сколько байтов получили */
buf[nb] = '\0';
printf("Packet contains \"%s\"\n",buf);    /* Текст полученного сообщения */
close(sd);
}



Добавлено через 9 минут и 27 секунд
Цитата(GrayCardinal @  7.11.2007,  11:12 Найти цитируемый пост)
ой какая муть. извините, не сдержался

Я так и не понял, к кому это относилось????????????????? smile 

Это сообщение отредактировал(а) Олег2005 - 7.11.2007, 16:55
PM MAIL WWW MSN   Вверх
Sharkfire
Дата 7.11.2007, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Спасибо канеша за инфу.... но я такине понял что мне делать!!
Мне нужен прост работающий класс...  smile  smile  smile  smile 
PM MAIL ICQ   Вверх
xvr
Дата 7.11.2007, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Sharkfire @ 7.11.2007,  16:34)
smile 

Так а чо мне делать то??
Вы тут так красиво раскритиковали мой код (кстате все материалы для него взяты с форума єтого)
а что надо конкретно исправить не сказазли???!!  smile 

Кулас будет использоватся тольком моей программой и тольков среде C++ Builder 2006  smile

Для начала надо определиться ГДЕ вы собираетесь принимать свои UDP пакеты:

Если вы хотите использовать WSAAsyncSelect, то вам нужно окно, которое будет принимать нотификационные сообщения (это может быть любое окно - например главная форма приложения или любая другая), и BEGIN_MESSAGE_MAP/END_MESSAGE_MAP нужно будет вставить в тело именно этой формы. Handle окна можно будет достать через проперть Handle

Если вы хотите просто читать из сокета (блокирующе), то вам придется создать для этого thread (см TThread)

PM MAIL   Вверх
Олег2005
Дата 7.11.2007, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

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



Цитата(xvr @  7.11.2007,  17:05 Найти цитируемый пост)
Если вы хотите просто читать из сокета (блокирующе), то вам придется создать для этого thread (см TThread)

Ну я бы сказал - потоки ему ни к чему - в моем примере чистые блокирующие сокеты - надо только все с умом переделать - комментов в проге много - в соответствии со схемой взаимодействия - аттач

Присоединённый файл ( Кол-во скачиваний: 9 )
Присоединённый файл  Doc2.doc 23,00 Kb
PM MAIL WWW MSN   Вверх
Sharkfire
Дата 8.11.2007, 23:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Ок. Я собсвенно чо сел писать свой класс не от нефиг делать!

У меня обычный TUdpSocket не пашет
када RemotePort = LoaclPort и я шлю пакет на свой IP.

Та же самая прога .... на TNMUdp пашет!! на теже порты!!!  smile 
PM MAIL ICQ   Вверх
xvr
Дата 8.11.2007, 23:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(Sharkfire @ 8.11.2007,  23:16)
Ок. Я собсвенно чо сел писать свой класс не от нефиг делать!

У меня обычный TUdpSocket не пашет
када RemotePort = LoaclPort и я шлю пакет на свой IP.

Та же самая прога .... на TNMUdp пашет!! на теже порты!!!  smile

TUdpSocket клиент, а тебе нужен сервер :( Если ты не хочешь органически вплетать код обслуживания сокета во все остальное приложение и не хочешь делать оконный компонент, который мог бы получать нотификации через WSAAsyncSelect, то остается только TThread (TTcpServer использует ее)

Посмотри на исходник в присоединенном файле


Это сообщение отредактировал(а) xvr - 9.11.2007, 00:07

Присоединённый файл ( Кол-во скачиваний: 6 )
Присоединённый файл  1.cpp 2,77 Kb
PM MAIL   Вверх
Sharkfire
Дата 9.11.2007, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


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

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



Да не очень я хочу так віворачиватся... почему то в 6-м билдере ... этой проблемы не было....
и я так понимаю.. что понятия "сервер" нет в UDP т.к как нет факла подключения.

Ппоробую порыцца в вашем примере , спасибо..... 

P.S. Кстате, соеденил мой класс с окном,  

Цитата(xvr @  7.11.2007,  17:05 Найти цитируемый пост)
BEGIN_MESSAGE_MAP/END_MESSAGE_MAP нужно будет вставить в тело именно этой формы. Handle окна можно будет достать через проперть Handle


сделал всё как сказали... при запуске пишет стэковерфлоу на строке   END_MESSAGE_MAP(TForm6)

PM MAIL ICQ   Вверх
Олег2005
Дата 9.11.2007, 00:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 421
Регистрация: 26.5.2005
Где: Рига Латвия

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



Цитата(Sharkfire @  9.11.2007,  00:29 Найти цитируемый пост)
и я так понимаю.. что понятия "сервер" нет в UDP т.к как нет факла подключения.

Нет, это неверно
Понятие UDP-сервера есть - я ведь высылал схему взаимодействия
UDP-сервер запускается и висит на recvfrom() - ждет, когда кто-то пришлет какой запрос и отвечает sendto() - если надо.
Типичный UDP-сервер  - это DNS-сервер
PM MAIL WWW MSN   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




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


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

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