Skip to main content

winsock

Аватар пользователя забыл_пароль
Не в сети
Гражданин
Зарегистрирован: 29.10.2005
Сообщения: 1414
Баллы: 1427
winsock

Появилась необходимость написать что-то вроде http-бота (маленького такого демона), который висит в системе и отвечает всем, кто заходит на localhost определённым образом. Всё бы ничего, но написать надо на WinSock (и ничего больше - на всём остальном я и сам могу) Smile Не могу вспомнить, как заставить отвечать сокет на все запросы... Вот, что я восстановил в своей голове:

...<br />
var<br />
  s:tsocket;<br />
  D:WSAData;<br />
  a:TSockAddr;<br />
  buf:string;<br />
  ...<br />
begin<br />
  ...<br />
  if WSAStartup($101,D)<>0 then exit;<br />
  A.sin_family:=AF_INET;<br />
  A.sin_addr.S_addr:=inet_addr(pchar("127.0.0.1"));<br />
  S:=socket(AF_INET,SOCK_STREAM,0);<br />
  if S=INVALID_SOCKET then showmessage('invalid socket');<br />
  A.sin_port:=htons(80);<br />
  if bind(S,A,sizeof(A))<> 0 then showmessage('no bind'); { вот тут уже не уверен }<br />
  ...<br />
    [а что вот тут?]<br />
  ...<br />
  WSACleanup;<br />
...

Проблема не столько в том, как послать, а в том, как обнаружить коннект? Вроде надо использовать licten и recv/send ...

Аватар пользователя забыл_пароль
Не в сети
Гражданин
Зарегистрирован: 29.10.2005
Сообщения: 1414
Баллы: 1427
winsock

немного поломал голову и вот что получил...

 ...<br />
 listen(s,100);<br />
 while true do begin<br />
   i:=sizeof(a);<br />
   sockc:=accept(s,@a,@i);<br />
   if sockc<>-1 then<br />
     if recv(sockc,buf,100,0) <> -1 then showmessage(s);<br />
 end;<br />
 ...

Клиенты могут коннектиться, но, как только они начинают передавать данные происходит ошибка... Что не так? Не ужели этим никто не занимался?

Аватар пользователя Aven
Не в сети
Гражданин
Зарегистрирован: 08.05.2007
Сообщения: 1318
Баллы: 1375
winsock

WSAAsyncSelect(WorldSock,Handle, WM_WorldSocketEvent,world_sock_event_mask);</p>
<p>...</p>
<p>форма:<br />
    procedure WMWorldSocketEventHandler(var Msg:TMessage);message WM_WorldSocketEvent;</p>
<p>...<br />
procedure TForm1.WMWorldSocketEventHandler(var Msg:TMessage);<br />
var<br />
   Sock:TSocket;<br />
   SockError,AcceptResult:Integer;<br />
   Addr:TSockAddr;<br />
   Len,offs,Block:Integer;<br />
   out_buff: array of byte;</p>
<p>   Player: TPlayer;  <br />
begin<br />
   Sock:=TSocket(Msg.WParam);<br />
   SockError:=WSAGetSelectError(Msg.lParam);<br />
   if SockError<>0 then<br />
    begin<br />
     CloseSocket(Sock);<br />
     Exit<br />
    end;<br />
   case WSAGetSelectEvent(Msg.lParam) of<br />
    FD_Read:<br />
     begin<br />
      //то что пришло нам<br />
     end;<br />
    FD_Accept:<br />
     begin<br />
      AcceptResult:=Accept(Sock,@Addr,@Len);<br />
     end;<br />
    FD_Close:<br />
     begin<br />
      Shutdown(Sock,SD_Send);<br />
      CloseSocket(Sock);<br />
     end;<br />
    FD_Write:<br />
     begin</p>
<p>     end;<br />
   end<br />
end;

Аватар пользователя забыл_пароль
Не в сети
Гражданин
Зарегистрирован: 29.10.2005
Сообщения: 1414
Баллы: 1427
winsock

Вообще получать мне вовсе не нужно было, а тоько отправлять при запросе. Формы я тоже не использовал - я изначально решил, что винсокс, потому, что мне нужен был минимальный размер.
Кстати, в каком модуле определено WM_WorldSocketEvent.
Хотя уже не важно, вот что у меня получилось:

program httpbot;<br />
uses<br />
  ...,winsock;</p>
<p>var<br />
  senddata,page:string;<br />
  inf:TWSADATA;<br />
  i,socks,sockc: integer;<br />
  sockaddr: TSockAddr;<br />
  s: array[1..2000] of Char;</p>
<p>begin<br />
  senddata:='то, что будет написано при заходже на сервер';<br />
  page:='HTTP/1.1 200'+chr(10)+chr(13);<br />
  page:=page+'Content-length: '+inttostr(length(senddata)+1)+chr(10)+chr(13);<br />
  page:=page+'Content-type: text/html; charset=windows-1251'+chr(10)+chr(13);<br />
  page:=page+'Connection: Close'+chr(10)+chr(13)+chr(10)+chr(13);<br />
  page:=page+senddata;<br />
  WSAStartup(MAKEWORD(2,0),inf);<br />
  socks:=socket(AF_INET,SOCK_STREAM,0);<br />
  sockaddr.sin_family := AF_INET;<br />
  sockaddr.sin_port := htons(80);<br />
  sockaddr.sin_addr.S_addr := htonl(INADDR_ANY);<br />
  bind(socks,sockaddr,sizeof(sockaddr));<br />
  listen(socks,3);<br />
  i:=sizeof(sockaddr);<br />
  while true do begin<br />
    sockc:=accept(socks,@sockaddr,@i);<br />
    if sockc<>-1 then begin<br />
      if recv(sockc,s,Length(s),0) <>-1 then begin<br />
        for i:=1 to length(page) do s[i]:=page[i];<br />
        send(sockc,s,Length(s),0);<br />
      end;<br />
    end;<br />
  end;<br />
end.

может кому пригодится Smile

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".