Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

UDP

367
05 февраля 2007 года
Meatcoins
303 / / 18.01.2006
Пытаюсь написать простенькую программку соединения по UDP. Вот, что получилось:
(Это что-то типа клиента!)
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
buf: string;
begin
UdpSocket1.LocalHost := Edit1.Text;
UdpSocket1.LocalPort := Edit2.Text;
UdpSocket1.RemoteHost := Edit3.Text;
UdpSocket1.RemotePort := Edit4.Text;

buf := 'Hello!';
UdpSocket1.Open;
UdpSocket1.Sendln(buf,#$D#$A);  // Так всё посылается, но не соедиеняется!
UdpSocket1.Close;

end;


(А это что-то типа сервера!)
 
Код:
procedure TForm1.UdpSocket1Receive(Sender: TObject; Buf: PAnsiChar; var DataLen: Integer);
var
s: string;
begin
UdpSocket1.Open; //Не работает!
s := UdpSocket1.Receiveln(#$D#$A);
UdpSocket1.Close;
MessageBox(0,PChar(s),PChar(s),MB_OK);
end;


Сервер нифига не работает!
Отлаживал с помощью Ethereal'а!
Там всё видно - посылается пакет по UDP - всё нормально, но тут же шлётся обратно ICMP-сообщение - port unreachble (порт недостижим)!
Почему так???
Хотя вроде бы я для сервера и клиента указал использовать 3000-й порт...
3.3K
05 февраля 2007 года
GENA_DJ
123 / / 08.03.2005
UdpSocket1 - что за объект? У сервера инициализацию этого объекта забыл написать.

Возможно, нужно использовать htons() для преобразования номера порта в стандарте INTEL (младшие биты по младшему адресу) в сетевой стандарт (старшие биты по младшему адресу).
367
05 февраля 2007 года
Meatcoins
303 / / 18.01.2006
[quote=GENA_DJ]UdpSocket1 - что за объект?[/quote]

Код:
unit udp;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Sockets;

type
  TForm1 = class(TForm)
    UdpSocket1: TUdpSocket; //Вот!
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure UdpSocket1Receive(Sender: TObject; Buf: PAnsiChar;
      var DataLen: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;


[quote=GENA_DJ]
У сервера инициализацию этого объекта забыл написать.
[/quote]
В смысле? А что там писать?
355
05 февраля 2007 года
<SCORP>
786 / / 21.10.2006
ну может там где-то надо указать, что это именно серверный сокет? вообще, серверным сокетам обычно делают Listen. я, конечно, не знаю толком что делает метод Open.... но вообще обычно у клиента конект, у севера лисен
а вообще, УДП сокеты без постоянного соединения работают
367
05 февраля 2007 года
Meatcoins
303 / / 18.01.2006
[quote=<SCORP>]но вообще обычно у клиента конект, у севера лисен
а вообще, УДП сокеты без постоянного соединения работают[/quote]
Ну это, конечно, да - никакого логического соединения, как в TCP тут нет. Просто я посылаю данные, а принять не могу - мистика какая-то!
Хотя, вроде бы, всё должно работать...
Мысль:
А может надо попробовать поток Thread создать?
Типа CreateThread...
И в этом потоке Listening...
355
05 февраля 2007 года
&lt;SCORP&gt;
786 / / 21.10.2006
Listen обычно асинхронный вызов. есть вообще два варианта реализации этого сокета -- он сам инкапсулирует поток, в котором делает recieve, а тебе предоставляет интерфейс в виду событий. или он тебе напрямую предоставляет блокирующий вызов recieve.
вот тебе надо найти там что-то из этих двух
3.3K
05 февраля 2007 года
GENA_DJ
123 / / 08.03.2005
Цитата: Meatcoins

В смысле? А что там писать?


С объектами делфей не знаком. Наверное, указать порт, на котором нужно данные принимать.

Если перейти на уровень API - listen использовать не нужно, это прерогатива TCP сокетов. Достаточно создать сокет, потом посредством bind связать с интерфейсом и портом, затем вызывать в цикле recvfrom, чтобы пакеты принимать.

Примерный код

Код:
#include<stdio.h>
#include<windows.h>
int main(int argc, char * argv[])
{
#define blen 0x4000

    struct WSAData
        WSAData;

    SOCKADDR_IN
        loca_sin,
        dest_sin;

    SOCKET
        sock;

    int
        fromlen,
        len;
    char
        sb[blen];

    if(WSAStartup(MAKEWORD(2,2),&WSAData)!=0)
    {
        return 0;
    }
    if((sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP))==INVALID_SOCKET)
    {
        WSACleanup();
        return 0;
    }
    loca_sin.sin_family = PF_INET;
    loca_sin.sin_addr.s_addr = inet_addr("127.0.0.1");//Можно и INADDR_ANY поставить, если работать со всеми интерфейсами
    loca_sin.sin_port = htons(66);//ловим на 66 порту

    if(bind(sock,(LPSOCKADDR)&loca_sin,sizeof(loca_sin))==SOCKET_ERROR)
    {
        closesocket(sock);
        WSACleanup();
        return 0;
    }

    for(;;)
    {
        fromlen=sizeof(dest_sin);
        if((len=recvfrom(sock, sb, 0x4000, 0, (LPSOCKADDR)&dest_sin, &fromlen))==SOCKET_ERROR)
        {
            closesocket(sock);
            WSACleanup();
            return 0;
        }
        printf("recived\n");
    }
    closesocket(sock);
    WSACleanup();
    return 0;
}
367
06 февраля 2007 года
Meatcoins
303 / / 18.01.2006
Загнал Rambler по поиску и нашёл аналогичную тему, и примерно проблема как у меня! И даже приведён похожий на мой пример программы:
[quote=Meatcoins]
 
Код:
procedure TForm1.UdpSocket1Receive(Sender: TObject; Buf: PAnsiChar; var DataLen: Integer);
var
s: string;
begin
UdpSocket1.Open; //Не работает!
s := UdpSocket1.Receiveln(#$D#$A);
UdpSocket1.Close;
MessageBox(0,PChar(s),PChar(s),MB_OK);
end;

[/quote]
И вопрос был, что эта функция даже не вызывается!

Если кому-то понадобится, то вот, что я нашёл:
Правда пока не разобрался, но откомпилировал - работает!
Код:
unit udp;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, Winsock, StdCtrls;

const
//  HST_BROADCAST: String = '255.255.255.255';
  MAX_UDP_SIZE: Integer = 8192;
  WM_ASYNC = WM_USER + 1;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  public
    FHandle: HWND;
    procedure SockWND(var AMsg: TMessage); message WM_ASYNC;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}





procedure TForm1.SockWND(var AMsg: TMessage);
var
  Buffer: array [0..8191] of Char;
  Size: Integer;
  SockAddr: TSockAddrIn;
begin
  with AMsg do
    case Msg of
    WM_ASYNC:
    begin
      case WSAGetSelectEvent(LParam) of
        FD_READ:
        begin
          FillChar(Buffer, 8192, #0);
          Size := SizeOf(SockAddr);
          recvfrom(WParam, Buffer[0], MAX_UDP_SIZE, 0, SockAddr, Size);
          ShowMessage(StrPas(@Buffer));
          DeallocateHWnd(FHandle);
          closesocket(WParam);
          WSACleanup;
        end;
      end;
    end
    else
      DefWindowProc(FHandle, Msg, WParam, LParam);
    end;
end;



procedure TForm1.Button1Click(Sender: TObject);
var
  FWSAData: TWSAData;
  FSockAddr: TSockAddrIn;
  FSocket: HWND;
  Option: Boolean;
  Data: String;
  SrvHost: String;
begin
  WSAStartup($0101, FWSAData);
  FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  with FSockAddr do
  begin
    SrvHost := Edit1.Text;
    sin_addr.S_addr := inet_addr(PChar(SrvHost));
  //  sin_addr.S_addr := INADDR_BROADCAST;
    Option := True;
    SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, PChar(@Option), SizeOf(Option));
    sin_port := htons(6767);
    sin_family := AF_INET;
  end;
  Data := 'My first broadcast message!!!';
  SendTo(FSocket, Data[1], Length(Data), 0, FSockAddr, SizeOf(FSockAddr));
  closesocket(FSocket);
  WSACleanup;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  FWSAData: TWSAData;
  FSockAddr: TSockAddrIn;
  FSocket: HWND;
  Option: Boolean;
  SrvHost: String;
begin
  WSAStartup($0101, FWSAData);
  FSocket := socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  with FSockAddr do
  begin
    SrvHost := Edit2.Text; // &#221;&#242;&#238; IP &#241;&#229;&#240;&#226;&#224;&#234;&#224; (&#242;.&#229;. &#237;&#224;&#248;&#229;&#233; &#236;&#224;&#248;&#232;&#237;&#251;)
    sin_addr.S_addr := inet_addr(PChar(SrvHost));
    Option := True;
    SetSockOpt(FSocket, SOL_SOCKET, SO_BROADCAST, PChar(@Option), SizeOf(Option));
    sin_port := htons(6767);
    sin_family := AF_INET;
  end;
  bind(FSocket, FSockAddr, SizeOf(FSockAddr));
  FHandle := AllocateHWnd(SockWND);
  WSAAsyncSelect(FSocket, FHandle, WM_ASYNC, FD_READ);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if Edit2.Text = '{Your IP1}' then Edit2.Text := '{Your IP2}'
else
Edit2.Text := '{Your IP1}';
end;

end.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог