Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

WinSock сервер, события [D6, WinXP]


Страницы:   1 2 3

Delpher_Gray ©   (2004-02-27 06:43:00) 

Как сделать, чтоб программа воспринемала сообщения от сокета ?
Вот код небольшой программки:
...

var
 Form1: TForm1;
 Data: WSAData;
 Sock: TSocket;
 Addr: TSockAddr;
 Msg: integer;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
 if WSAStartup($101, Data) <> 0 then
   Die;

 Sock := Socket(AF_INET, SOCK_STREAM, IPPROTO_IP);

 if Sock = INVALID_SOCKET then
   Die;
 
 WSAAsyncSelect(Sock, Form1.Handle, Msg, FD_READ or FD_WRITE or FD_CLOSE);

 Addr.sin_family := AF_INET;
 Addr.sin_addr.S_addr := INADDR_ANY;
 Addr.sin_port := htons(1379);

 Bind(Sock, Addr, SizeOf(Addr));
 Listen(Sock, SOMAXCONN);
end;


Сокет прослушивает порт, подскажите как сделать чтоб можно было обрабатывать события сокета: соединение, рассоединение, чтение данных и прочее...

Заранее благодарен !


Digitman   (2004-03-04 08:21:00) [1]


> привильно ли всё сделано


неправильно.

в обработчике события FD_ACCEPT не следует ничего передавать вновь подключившемуся клиенту

дождись FD_WRITE (оно обязательно возникнет следом за FD_ACCEPT, как минимум однократно), и вот уже в обработчике FD_WRITE ты имеешь полное право выполнять свою SendString() для того гнезда, которое возбудило это событие


Verg   (2004-03-03 20:14:00) [2]


> Delpher_Gray ©   (03.03.04 20:01) [42]
> >Кого спрашиваешь? - все равно, типа, "никого не слушаешь"
> :)
> Всё же стараюсь....... ;)
>
> Дело не в размере, я просто хочу разобраться сначала и до
> конца как всё это работает, без всяких Classes.......


Поступай как хочешь, но classes тоже писали не придурки, единственной целью которых было типа увеличить размер твоей любимой программы.
Через WinAPI, говоришь. А classes работает, конечно, через "черный ход"? Ага...

В чем ты хочешь разобраться? В окнах, их классах, собщениях, способах их обработки и проч.? - иди в WinAPI форум.
Ты смешал все в одну большую кучу, и хочешь с этим  одновременно разбираться.... Мухи от котлет отдели пока....


Delpher_Gray   (2004-03-03 20:01:00) [3]

>Кого спрашиваешь? - все равно, типа, "никого не слушаешь" :)
Всё же стараюсь....... ;)

Дело не в размере, я просто хочу разобраться сначала и до конца как всё это работает, без всяких Classes.......


Verg   (2004-03-03 19:55:00) [4]


> ioctlsocket(WParam, FIONREAD, Longint(OffSet));


1. Этого НЕ надо.

2. LParam в case - низя - там в LParamHi - код ошибки при исключительных ситуациях, только LparamLo...,
Кстати, значит, ScktComp так и не посмотрел....

Поверхеностно подходите к задаче, м.ч., как я посмотрю


> Всё работает, но привильно ли всё сделано ??


Кого спрашиваешь? - все равно, типа, "никого не слушаешь" :)


> Ага, как-же :)) Так прога весит 15.5 кб, и пашет, а с модулем:
> 150


Т.е. уже все? - вседелает и весит 15,5 ? Полнофункциональная ? :)))

Эх, "вюноша бледный...",...


Delpher_Gray   (2004-03-03 19:40:00) [5]

>С Classes не так уж и "распухает"
Ага, как-же :)) Так прога весит 15.5 кб, и пашет, а с модулем: 150

>Тебе не обойтись без этого модуля для сервера, либо по-сути тебе его придется "воспроизвести" врукопашную.
Юзаю KOL и WinAPI :)

2Digitman:
Я нашёл решение, очени, правильно ли...
...

procedure SockMSG(HWnd, Msg, WParam, LParam: longint); stdcall;
begin
 if Msg = WM_SOCK then
   case LParam of
     FD_ACCEPT:
     begin
       MsgOk('FD_ACCEPT');
       ASock := accept(Sock, nil, nil);
       WSAAsyncSelect(ASock, Wnd, WM_SOCK, FD_READ);
       SendString('FD_ACCEPT', ASock);
     end;
     FD_READ:
     begin
       MsgOk('FD_READ');
       ioctlsocket(WParam, FIONREAD, Longint(OffSet));
       Received := recv(WParam, Buff[1], SizeOf(Buff), 0);
       MsgOk(Int2Str(Received)+' èç '+Int2Str(OffSet));
     end;
   end;
end;

...

SetWindowLong(Wnd, GWL_WNDPROC, Longint(@SockMSG));


Так вот :) Всё работает, но привильно ли всё сделано ??


Verg   (2004-03-03 19:11:00) [6]

1. С Classes не так уж и "распухает"
2. Тебе не обойтись без этого модуля для сервера, либо по-сути тебе его придется "воспроизвести" врукопашную.

TList, TStringList, TMemory и прочий Stream, Thread и т.д. - вещи функционально необходимые для серъезного серверного приложения.
Писать "самопальные"? - в конце концов у тебя получится тот же Classes....., тот же велосипед.

Я так считаю (не люблю писать ИМХО :)))


Digitman   (2004-03-03 18:46:00) [7]


> Как её преобразовать для SetWindowLong ?
>
> В Classes это делается так:
> SetWindowLong(Result, GWL_WNDPROC, Longint(MakeObjectInstance(Method)));


ну та к посмотри, как это делается в Classes, и сделай по образу и подобию !!


Delpher_Gray   (2004-03-03 18:24:00) [8]

>бросай "сети"

У меня нет знаний в работе с ситемой, а именно с сообщениями, окнами и т.п...
Поэтому так трудно даётся.
На TServerSocket и TClientSocket я писал довольно сложные программки, работающие 100% ;))

Подскажи плиз.......
SetWindowLong(Wnd, GWL_WNDPROC, ???); - ошибка- это так объяснил... На самом деле знаю почему ошибка, потому что переменная ???, где у меня Serv.SockWND - должна быть типа Pointer а у меня процедура !
Как её преобразовать для SetWindowLong ?

В Classes это делается так:
SetWindowLong(Result, GWL_WNDPROC, Longint(MakeObjectInstance(Method)));

Где Method - процедура, типа TWndMethod:
type
 TWndMethod = procedure(var Message: TMessage) of object;


Digitman   (2004-03-03 17:48:00) [9]


> Delpher_Gray ©   (23.01.04 13:21) [35]


бросай "сети"

у тебя не хватает базовыхзнаний по Delphi Objectpascal


Digitman   (2004-03-02 13:29:00) [10]


> почему у меня SockWND(var AMsg: TMessage); не работает !??


а почему это должно работать ?

этот метод будет вызван ТОЛЬКО в случае вызова метода Dispatch() твоего объекта TServer()

TServer = class
private
  procedure SockWND(var AMsg: TMessage); message WM_SOCK;
protected
  procedure Run;
end;
...
procedure TServer.Run;
var
 Msg: TMsg;
begin
 while GetMessage(Msg, 0, 0, 0) do
  if Msg.hWnd = Wnd then
    Dispatch(Msg.Message)
  else
    DispatchMessage(Msg);
end;


Polevi   (2004-03-02 13:24:00) [11]

>Ты лучше подскажи почему у меня SockWND(var AMsg: TMessage); не работает !??
а где она у тебя вызыввется ?


Delpher_Gray   (2004-03-02 13:18:00) [12]

Cancel := true; Можно писать например если принято какое-нить сообщение от сокета.

С мьютексом да будет так:
 if WaitForSingleObject(CreateMutex(nil, false, 'Server'), 0) <> wait_TimeOut then
 begin
   ...
 end;


Всё работает нормально...

Ты лучше подскажи почему у меня SockWND(var AMsg: TMessage); не работает !??


Digitman   (2004-03-02 13:12:00) [13]

а уж если тебе нужен мьютекс, то почему затираешь значение его хэндла ? закрывать-то потом мьютекс как будешь в ДАННОМ процессе, если ты хэндл его потерял ? понадеешься на ОС что ли ?


Digitman   (2004-03-02 13:10:00) [14]


> Delpher_Gray ©   (02.03.04 13:05) [29]
> Цикл крутится, пока Cancel = false


ну и в каком месте ты намерен взводить этот флаг ?


> Mutex нужен чтоб избежать повторного запуска программы.


на кой ляд тебе это сейчас нужно ? не меси ты кислое с пресным ! научись корректно работать с Winsock, потом уже будешь накручивать в программе иную функц-ть , ну никак не связанную с транспортом !


Delpher_Gray   (2004-03-02 13:05:00) [15]

>если while-цикл крутится бесконечно
Цикл крутится, пока Cancel = false

Mutex нужен чтоб избежать повторного запуска программы.

>Polevi ©   (02.03.04 12:41) [22]
Хе, а про это я уже забыл :) Давно было...
Но тут проблема...
Почему-то когда я сам создаю окно (CreateWindowEx), то процедура приёма сообщений procedure TServer.SockWND(var AMsg: TMessage); не работает !
А если обрабатывать сообщения в цикле, то всё работает !? Как сделать чтоб заработала procedure TServer.SockWND(var AMsg: TMessage); ?


Digitman   (2004-03-02 13:01:00) [16]

пардон ..

да там Peekmessage !!

тело цикла даже в одной итерации не выполнится, и цикл будет прерван, если на момент PeekMessage сообщений в очереди нет


Digitman   (2004-03-02 12:59:00) [17]

и еще .. подумай, каким образом твой конс.процесс м.б. корректно завершен юзером, если while-цикл крутится бесконечно


Digitman   (2004-03-02 12:57:00) [18]


> Wnd := CreateMutex(nil, false, 'Server');
...
> Wnd := CreateWindowEx(WS_EX_TOOLWINDOW, wc.lpszClassName,
>      '', WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, nil);


а это что за бред ?

в Wnd сначала пишется хэндл мьютекса (на кой шут он здесь - тоже непонятно), и тут же затирается хэндлом окна ...

а Stream зачем ?
а Sleep ? зачем ?

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


Digitman   (2004-03-02 12:52:00) [19]


>      ASock := accept(Sock, nil, nil);
>      ASock := WSAAsyncSelect(ASock, Wnd, WM_SOCK, FD_READ);


это что за бред ?

в ASock записывается хэндл нового гнезда и тут же затирается !!


Polevi   (2004-03-02 12:46:00) [20]

>Delpher_Gray ©   (02.03.04 12:42) [23]
Polevi ©   (02.03.04 12:41) [22]


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо