Форум: "Сети";
Текущий архив: 2002.11.25;
Скачать: [xml.tar.bz2];
ВнизПрограммирование WinSocket Найти похожие ветки
← →
Subfire (2002-09-29 02:25) [0]Задачка простенькая...короче, создаю сокет, все супер...для получения сообщения от сокета использую WSAAsyncSelect.....
Но например, если я пишу приложение, где нет окна (ну не нужно оно там...это сервак...мне важен размер приложения), то использовать WSAAsyncSelect не могу - так как это Message ориентированный метод...а окна нет, значит хендла нет и месседж посылать некому... :(
По поводу функци select в апи документации написано че-то невнятное..короче, этим методом я могу получить состояние сокета, но распознать какого типа никак...т.е. мне в приложении нужно помнить состояние сокета - т.е. если его состояние listening, значит смена статуса значит - accept...А если статус Accepted - значит у нас сигнал READ....но это же криво...можно сделать - но я не верю, что так все пишут...
Вот...есть еще WSAEventSelect .....по идее то что нужно...Ей передается параметр типа hEventObject....но 1) Х/З как это работает...пока не разобрался...2) Ни в Delphi6-7, ни в 5C++ билдере нету прототипа этой функции....
Я уже перелопатил кучу исходников всяких сетевых компонент...но МЛИН, они все VCL и ессно имеют хендл формы.. :)
Есть еще вариант - просто на АПИ без VCL создать форму....сделать невидимой и испольовать ее хендл....размер будет небольшой...НО ЭТО ЖЕ ТОЖЕ КРИВО!!! Неужели нет другова выхода...а как консольные утилиты работают тады?!
Может кто подскажет?! Если есть исходники (на Delphi,C++) шлите, плиз...
← →
Rouse_ (2002-09-29 02:35) [1]Попробуй это сокет на АПИ
program Small_socket_server;
{$M 16384,2097152}
uses
Windows,
Winsock,
SysUtils;
const
nport:smallint = 500;//порт - любой (я взял 500-й)
var
WSAData:TWSAData;
MySockAddr:sockaddr_in;
descriptor,srvsocket:TSocket;
res,thread_id:cardinal;
type MyPChar = array [0..255] of Char;
threadvar //тут переменные для потока
ColBytes: Cardinal;
thread_buffer: MyPChar;
_wsaerror,rcvd_bytes:Cardinal;
answer: MyPChar;
threadsocket:TSocket;
var F: Text;
procedure WriteS(S: PChar);
var n: integer;
begin
AssignFile(F, "logs.txt");
{$I-}
Append(F);
{$I+}
if IOResult <> 0 then ReWrite(F);
{ for n := 1 to rcvd_bytes do
Write(F,S[n-1]);
Writeln(F);
}
Writeln(F,S);
Close(F);
end;
procedure InitializeSrvSocket;
begin
res:=WSAStartup($0101,WSAData);
if res<>0 then Halt;
MySockAddr.sin_addr.S_addr:=INADDR_ANY;
MySockAddr.sin_port:=htons(nport);
MySockAddr.sin_family:=AF_INET;//это семейство протоколов кажется. их много...
descriptor:=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//пытаемся создать сокет - если он уже есть
//на данном порту - закрываемся
if descriptor=INVALID_SOCKET then Halt;
res:=bind(descriptor,MySockAddr,SizeOf(MySockAddr));
if res<>0 then Halt;
res:=listen(descriptor,SOMAXCONN);//SOMAXCONN - это вроде 5 клиентов максимум? поправьте если ошибаюсь
if res<>0 then Halt;
//при инициализации сокета никаких ошибок не выдаётся, что разумеется легко поправимо (если надо)
end;
procedure ThreadExecProc; //процедура потока
type MyCharArray = array [0..255] of Char;
RIOpenComm = record
FunNum: Byte;
InQueue: Word;
OutQueue: Word;
Size: Word;
ComName: MyCharArray;
end;
var OpenC: RIOpenComm;
NotRead: Boolean;
P: MyCharArray;
PCS: PChar;
POpenC : ^RIOpenComm;
V: OleVariant;
SS: AnsiString;
begin
threadsocket:= srvsocket;
// answer:="Соединено"+Chr(13)+Chr(10); //мессага клиенту
answer:="Connected"+Chr(13)+Chr(10); //мессага клиенту
send(threadsocket,answer,Length(answer),0); //отправляем ответ клиенту что усё ОК
while true do begin //поток выполняется пока не произойдёт дисконнект
thread_buffer:=""; //чистим буфер
{ ColBytes := StrLen(answer);}
rcvd_bytes:=recv(threadsocket,thread_buffer,Length(thread_buffer),0); //ждём данных от клиента - строку
// тут всё просто либо мы получаем данные, либо rcvd_bytes=0 (нормальный дисконнект) либо фатальный дисконнект -
//тогда смотрим код последней ошибки
_wsaerror:=WSAGetLastError; //тут мы его (код ошибки) и проверяем...
if (rcvd_bytes=0) or (_wsaerror=WSAECONNRESET) then begin //обрабатываем дисконнект
MessageBeep(0);
closesocket(threadsocket); //закрываем сокет
ExitThread(0); //выходим из потока
end;
// MessageBeep(0);
// answer:="Соединено"+Chr(13)+Chr(10); //мессага клиенту
Inc(Colbytes, 10);
SS := "Weigth = " + (IntToStr(ColBytes))+Chr(13)+Chr(10);
StrCopy(answer, PChar(ss));
send(threadsocket,answer,StrLen(answer),0); //отправляем ответ клиенту что усё ОК
// send(threadsocket,thread_buffer,Length(answer),0);
//# WriteS(thread_buffer);
// MessageBeep(0);
end; //end while
end;
begin
InitializeSrvSocket; //инициализируем сокет
while true do begin //крутим цикл
srvsocket:=accept(descriptor,nil,nil); //ждём соединения. именно просто ЖДЁМ - не жрём ресурсов проца
//(или по минимуму - таскинфо у меня показывал либо 0 либо 0.01% загрузки проца)
if srvsocket<>INVALID_SOCKET then begin //если всё успешно, то создаём поток для клиента
CreateThread(nil,0,@ThreadExecProc,nil,0,thread_id);
//далее ОТДЕЛЬНЫЙ поток работает с ОТДЕЛЬНЫМ клиентом, а прога снова ждёт коннекта другого клиента...
end;
end;
end.
Желаю удачи
← →
Polevi (2002-09-29 12:53) [2]>а окна нет, значит хендла нет и месседж посылать некому... :(
Forms.AllocateHwnd
← →
Subfire (2002-09-29 16:03) [3]Rouse_ © - пасиба...счаз сяду разбираться...
Polevi © - ты видимо не понял...т.к. форму я не использую, то и модуль forms из проекта исключен...собственно именно потому и формы нет - иначе размер программы слишком большой...
← →
Digitman (2002-09-30 08:39) [4]>Subfire
Проще всего будет задействовать event-механизм нотификации.
См. WSAEventSelect
← →
Polevi (2002-09-30 09:30) [5]>Digitman © (30.09.02 08:39)
тогда понадобиться Winsock2.pas
>Subfire (29.09.02 16:03)
выдрать кусок кода никак ?
procedure TTransport.Execute;
var
msg:TMsg;
wc:WNDCLASS;
FWaitEvent:THandle;
begin
FWaitEvent:=CreateEvent(nil,false,false,nil);
with wc do
begin
style:= 0;
lpfnWndProc:= @DefWindowProc;
cbClsExtra:= 0;
cbWndExtra:= 0;
hInstance:= 0;
hIcon:= 0;
hCursor:= 0;
hbrBackground:= 0;
lpszMenuName:= nil;
lpszClassName:= "FCTransportWndClass";
hInstance := HInstance;
end;
Windows.RegisterClass(wc);
FWindowHandle:=CreateWindowEx(WS_EX_TOOLWINDOW, wc.lpszClassName,
"", WS_POPUP {!0}, 0, 0, 0, 0, 0, 0, HInstance, nil);
while not Terminated do
case MsgWaitForMultipleObjects(1, FWaitEvent, False, INFINITE, QS_ALLEVENTS) of
WAIT_OBJECT_0:
Terminate;
WAIT_OBJECT_0 + 1:
while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do
if msg.message<>WM_SOCKETMESSAGE then
DispatchMessage(msg)
else
begin
case LOWORD(msg.lParam) of
FD_ACCEPT:DoAccept;
FD_CONNECT:DoConnect;
FD_CLOSE:DoClose;
FD_READ:DoRead;
FD_WRITE:DoWrite;
end;
end;
end;
end;
← →
Digitman (2002-09-30 09:53) [6]>Polevi
Совершенно необязательно. Достаточно декларировать 5-6 ф-ций, отсутствующих в Winsock.pas. Ради этих недостающих ф-ций нет смысла подменять штатный модуль на Winsock2.pas
← →
Polevi (2002-09-30 09:58) [7]2Digitman © (30.09.02 09:53)
согласен, но проще взять готовый и бросить его в директорию с проектом
← →
Digitman (2002-09-30 10:19) [8]>Polevi
Можно и так.
К.г., на вкус и цвет товарищей нет)....
Страницы: 1 вся ветка
Форум: "Сети";
Текущий архив: 2002.11.25;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.01 c