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;
UDP
(Это что-то типа клиента!)
Код:
(А это что-то типа сервера!)
Код:
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;
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-й порт...
Возможно, нужно использовать htons() для преобразования номера порта в стандарте INTEL (младшие биты по младшему адресу) в сетевой стандарт (старшие биты по младшему адресу).
Код:
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;
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]
В смысле? А что там писать?
а вообще, УДП сокеты без постоянного соединения работают
а вообще, УДП сокеты без постоянного соединения работают[/quote]
Ну это, конечно, да - никакого логического соединения, как в TCP тут нет. Просто я посылаю данные, а принять не могу - мистика какая-то!
Хотя, вроде бы, всё должно работать...
Мысль:
А может надо попробовать поток Thread создать?
Типа CreateThread...
И в этом потоке Listening...
вот тебе надо найти там что-то из этих двух
Цитата: 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;
}
#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;
}
[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;
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; // Ýòî IP ñåðâàêà (ò.å. íàøåé ìàøèíû)
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.
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; // Ýòî IP ñåðâàêà (ò.å. íàøåé ìàøèíû)
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.