![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
WinSock сервер, события [D6, WinXP]
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]