Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 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
14-82963
LeViSSSS
2002-11-06 13:57
2002.11.25
SOS


3-82585
Rule
2002-11-08 01:18
2002.11.25
Помогите пожалуста горит проект , извиняюсь за лемерство


3-82601
Vagrant
2002-11-04 09:50
2002.11.25
DBTreeView на основе VirtualTreeView


6-82889
drou
2002-09-23 19:32
2002.11.25
Как скачаты файлы из нета или с сетевого компа


3-82587
Mic_2000
2002-11-08 12:26
2002.11.25
Можно ли в IB вместо типа Date использовать TimeStamp





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский