Помощь - Поиск - Пользователи - Календарь
Полная версия: Сокеты и консоль
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Делфи
Unconnected
Привет всем.

Животрепещущий вопрос: возможно ли в консоли присвоить событию сокета (OnRead, например) свою процедуру? Например, Client.onread:=myevent;. Описать её (myevent) получается, а вот присвоить правильно - нет..
volvo
Можно посмотреть, как именно ты ее описываешь, и как пытаешься присвоить? smile.gif
Unconnected
program Project1;

{$APPTYPE CONSOLE}

uses
Windows,
SysUtils,
Classes,
ScktComp,
Graphics;

var server:TServersocket;

Procedure EVENT1(Sender: TObject; Socket: TCustomWinSocket);
begin
writeln(socket.receivetext);
end;

begin
server:=TServerSocket.create(nil);
server.port:=1001;
server.OnClientRead:=event1(); //<===здесь, во входных параметрах, определённо нужно что--то написать
Server.ServerType:=stNonBlocking;
server.Open;
while server.active do sleep(100);
end.


По идее, должно быть server.OnClientRead:=event1(sender,socket);, но ведь в консоли нет понятия Sender, да?smile.gif
volvo
По идее Event1 должен быть методом класса, поскольку в типе TSocketNotifyEvent есть указание:
type TSocketNotifyEvent = procedure (Sender: TObject; Socket: TCustomWinSocket) of object;

(2 слова в конце видишь? smile.gif )

Итого, решение тривиальное - обернуть всю работу с сокетом своим классом:
type
TFooClass = class(TObject)
server:TServersocket;
procedure Event1(Sender: TObject; Socket: TCustomWinSocket);
end;



Procedure TFooClass.Event1(Sender: TObject; Socket: TCustomWinSocket);
begin
writeln(socket.receivetext);
end;

var
obj: TFooClass;
begin
obj := TFooClass.Create;
with obj do begin
server:=TServerSocket.create(nil);
server.port:=1001;
server.OnClientRead:=event1;
server.ServerType := stNonBlocking;
server.Open;
while server.active do sleep(100);
end;
obj.Free;
end.
Можешь еще добавить try/finally, как положено, и создавать сокет в конструкторе класса TFooClass...
Unconnected
Спасибо, вот так компилируется, ООП сила:)
Только вот будут ли обрабатываться события при таком описании? Я вот ради интереса попробовал в консоли сделать клиентскую и серверную части, просто чтобы можно было передать строку текста с клиента на сервер, вот что получилось.

Сервер:

program Project1;

{$APPTYPE CONSOLE}

uses
Windows,
SysUtils,
Classes,
ScktComp,
Graphics;

type
TFooClass = class(TObject)
server:TServersocket;
procedure Event1(Sender: TObject; Socket: TCustomWinSocket);
end;

Procedure TFooClass.Event1(Sender: TObject; Socket: TCustomWinSocket);
begin
writeln(socket.receivetext);
end;

var
obj:TFooClass;
begin
obj:=TFooClass.Create;
with obj do begin
server:=TServerSocket.create(nil);
server.port:=1001;
server.OnClientRead:=event1;
server.ServerType:=stNonBlocking;
server.Open;
while server.active do sleep(100);
end;
obj.Free;
end.



Клиент:

program Project1;

{$APPTYPE CONSOLE}

uses
Windows,
SysUtils,
Classes,
ScktComp,
Graphics;

type
TFooClass = class(TObject)
client:Tclientsocket;
procedure Event2(Sender: TObject; Socket: TCustomWinSocket);
end;

var host:string;
key:string;
Procedure TFooClass.Event2(Sender: TObject; Socket: TCustomWinSocket);
begin
writeln('СОЕДИНЕНО!!!');
end;

var
obj:TFooClass;
begin
writeln('Введите IP-адрес сервера');
readln(host);
obj:=TFooClass.Create;
with obj do begin
client:=TClientSocket.create(nil);
client.port:=1001;
client.Onconnect:=event2;
client.clientType:=CtNonBlocking;
client.Address:=host;
client.Open;
repeat
key:='';
readln(key);
client.Socket.SendText(key);
until key='EXIT';
end;
obj.Free;
end.



Вот на событие OnConnecting обработчик срабатывает, а на OnConnect никак, строка тоже не передаётся, хотя пробовал своим проектом на VCL подсоединиться к консольному серверу - получилось.
volvo
Здесь помочь ничем не могу, это надо проверять, а проверять негде: я из-под Debian-а... Как попаду в WinXP - проверю...
volvo
Кстати... Вот сюда зайди: http://www.s2.org/flop.html , и посмотри исходники flop2 (предупреждаю сразу, написано на С, но вызовы API-функций они и в Африке вызовы), разбей их на клиент/сервер и пользуйся...
Unconnected
Цитата
Кстати... Вот сюда зайди: http://www.s2.org/flop.html , и посмотри исходники flop2 (предупреждаю сразу, написано на С, но вызовы API-функций они и в Африке вызовы), разбей их на клиент/сервер и пользуйся...


Ну, мне надо чтобы именно через Event'ы обрабатывались все события. Просто с одним человеком поспорил, он утверждал, что это невозможно - сделать запись в консоли client.Onconnect:=event2; и чтобы это вдобавок ко всему работало.. От программы достаточно, чтобы она хотя бы строку пересылала:)

volvo
Звони своему "одному человеку", и требуй с него ящик пива smile.gif

1) клиент:
// Client
program Project1;
{$APPTYPE CONSOLE}

uses
ScktComp, windows;

type
TCustomWinSocketA = class helper for TCustomWinSocket
function ReceiveTextAnsi: AnsiString;
end;
function TCustomWinSocketA.ReceiveTextAnsi: AnsiString;
begin
SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));
SetLength(Result, ReceiveBuf(Pointer(Result)^, Length(Result)));
end;


var
ClientMy:TClientSocket;
Msg:TMsg;

begin
ClientMy:=TClientSocket.Create(nil);
ClientMy.ClientType:=ctBlocking;
ClientMy.Address:='127.0.0.1';
ClientMy.Port:=8080;
ClientMy.Active:=true;
ClientMy.Socket.SendText('hello');
Sleep(5);
writeln(ClientMy.Socket.ReceiveTextAnsi);
while GetMessage(Msg,0,0,0) do DispatchMessage(Msg);
readln;
ClientMy.Free;
end.


2) сервер:
program Project1;
{$APPTYPE CONSOLE}

uses
ScktComp,SysUtils,windows;

type
TCustomWinSocketA = class helper for TCustomWinSocket
function ReceiveTextAnsi: AnsiString;
end;
function TCustomWinSocketA.ReceiveTextAnsi: AnsiString;
begin
SetLength(Result, ReceiveBuf(Pointer(nil)^, -1));
SetLength(Result, ReceiveBuf(Pointer(Result)^, Length(Result)));
end;

type
ServSock=class
serv:TServerSocket;
procedure ClientRead(Sender:TObject; Socket:TCustomWinSocket);
procedure ClientConnect(Sender:TObject; Socket:TCustomWinSocket);

public
constructor Create;
destructor Destroy; override;
end;

{ServSock}

constructor ServSock.Create;
Begin
inherited Create;
Serv:=TServerSocket.Create(nil);
Serv.ServerType:=stNonBlocking;
Serv.OnClientConnect:=ClientConnect;
Serv.OnClientRead:=ClientRead;
Serv.Port:=8080;
Serv.Active:=true;
End;

procedure ServSock.ClientRead(Sender:TObject; Socket:TCustomWinSocket);
var
a:ansistring;
Begin
a:=Socket.ReceiveTextAnsi;
Writeln(a);
if a='hello' then Socket.SendText('Hello goes back...');
End;

procedure ServSock.ClientConnect(Sender:TObject; Socket:TCustomWinSocket);
Begin
Socket.SendText('To Client: You are connected...');
End;

destructor ServSock.Destroy;
Begin
Serv.Free;
inherited Destroy;
End;

var
Server1:ServSock;
MSG: TMSG;

begin
Server1 := ServSock.Create;
try
while GetMessage(MSG, 0, 0, 0) do
begin
TranslateMessage(msg);
DispatchMessage(msg);
end;
finally
readln;
Server1.Free;
end;
readln;
end.
Все условия выполняются: все на Эвентах + окно консольное... Класс-Хелперы понадобились для того, чтоб программа была работоспособна на D2009 (без них в Юникодной версии Дельфи принимается совсем не то, что отсылается - баг в исходниках), если у тебя версия ниже 2009, то можешь Class Helper-ы смело убирать, а вместо ReceiveTextAnsi использовать обычный ReceiveText.

Проверялось на D2009 + WinXP SP3, работает... Запускается сначала сервер (как всегда), потом - клиент...
Unconnected
Volvo, спасибо, здорово, это его окончательно добило lol.gif good.gif Правда, за свой код выдавать не стал, ну для спора это значения не имеет) Вчера он говорил, что если это возможно, то он повесится) А про пиво не получится sad.gif , чел аж с Новгорода...(иначе сейчас бы меня на форуме не было))) .
Цитата

Все условия выполняются: все на Эвентах + окно консольное...


В выделенной части фразы подвох?smile.gif Теперь он прицепился к тому, что TranslateMessage(msg) и DispatchMessage(msg); - это Win32-функции, поэтому приложение не подходит под разряд консольного..

А ещё - мне становится страшно общаться со сверстником, который 14 лет из 16 программирует...
volvo
Ну, и что теперь, все, что подключает Windows.pas - будет считаться оконным? Тогда Сокеты вообще нельзя использовать, ибо они тоже там описаны. А консольное - потому, что GetStdHandle(STD_OUTPUT_HANDLE) вернет именно его хендл, а STD_OUTPUT_HANDLE это
Цитата(MSDN)
STD_OUTPUT_HANDLE (DWORD)-11 The standard output device. Initially, this is the active console screen buffer, CONOUT$.
( Цитата отсюда: http://msdn.microsoft.com/en-us/library/ms683231(VS.85).aspx ) Претензии есть к MSDN/Microsoft за то, что консольное приложение тоже может обрабатывать очередь сообщений? smile.gif Ну, извините, про ее (очередь) отсутствие ничего не было сказано...

Добавлено через 1 мин.
Цитата
мне становится страшно общаться со сверстником, который 14 лет из 16 программирует...
Что же он программировал в 3 года, интересно? Погремушку свою, или соску? Тогда я программирую вообще страшно представить, сколько лет smile.gif
Unconnected
Цитата, ICQ:

Цитата
>10 лет паскаля 12 бейсика 5 лет си++ и 2 года ассемблера риальне сделали свое=)
>>я за компом с 2-3 непомню когда батя посадил он тоже прогер
(он имел в виду параллельно изучать)

Причём через некоторое время я понял, что это как минимум наполовину не пустые слова...
Бедный парень, света белого не видит.. wacko.gif

Извиняюсь за оффтоп:)
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.