Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Не работает Select в сокетах

286
06 июня 2009 года
misha_turist
572 / / 28.11.2005
Доброго времени суток друзья.

Есть код
Код:
program Chat_Server;
uses constants, winsock, windows, sysutils;
const
 my_port = 666;
 max_connect_count = 64{SoMaxConn};
 
var Sockets:array[0 .. max_connect_count-1] of TSocket; // Њ ббЁў б®ЄҐв®ў
    connect_count  : integer;    // Љ®«ЁзҐбвў® ᮥ¤Ё­Ґ­Ё©
    Addr           : TSockAddr;  // Ђ¤аЁб Є«ЁҐ­в
    Data           : TWSAData;   // ’ ­­лҐ ® ЎЁЎ«Ё®вҐЄҐ б®ЄЄҐв®ў
    Len, I, J, n   : Integer;    //
    FDWriteSet,
    FDErrorSet,
    FDReadSet      : TFDSet;     // Њ­®¦Ґбвў® б®ЄҐв®ў Ј®в®ўле Є з⥭Ёо
    FDSetCount     : LongInt;    // Љ®«ЁзҐбвў® Ј®в®ўле б®ЄҐв®ў
    ReadTimeVal : TTimeVal;      // Џа®¬Ґ¦гв®Є ®¦Ё¤ ­Ёп з⥭Ёп
    msg_buffer        : array[0 .. 1024] of byte;  // ЎгдҐа б®®ЎйҐ­Ё©
    msg_buffer_length : integer;       // ¤«Ё­  бзЁв ­­ле ¤ ­­ле
    error : integer;             // Љ®¤ ®иЁЎЄЁ
{}    Arg : u_long;
{}    comand : dword;
begin
  writeln('Start my chat server.');
  writeln;
  write('Initialisation = ');
  if WSAStartup($0101, Data) <> 0 then
  begin
   ShowError('Error', WSAGetLastError);
   exit;
  end;
  writeln('Failed');
//  WSAStartup($101,Data);
  write('Create Socket = ');
  Sockets[0]:=socket(AF_INET,SOCK_STREAM,0{IPProto_TCP});
  if Sockets[0]<0 then
  begin
   ShowError('Error', WSAGetLastError);
   exit;
  end;
  writeln('Failed');
 
//  Sockets[0]:=Socket(AF_Inet,Sock_Stream,0);
  Addr.sin_family:=AF_Inet;
  Addr.sin_port:=HToNS(my_port);
  Addr.sin_addr.S_addr:=InAddr_Any;
  FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0);
  write('Open Socket = ');
  if bind(Sockets[0],@Addr,SizeOf(TSockAddr)) = Socket_Error then
  begin
   ShowError('Error', WSAGetLastError);
   exit;
  end;
  writeln('Failed');
//  Bind(Sockets[0],Addr,SizeOf(TSockAddr));
  write('Listen Socket = ');
  if Listen(Sockets[0],max_connect_count) = Socket_Error then
  begin
   ShowError('Error', WSAGetLastError);
   exit;
  end;
  writeln('Failed');
  connect_count := 1;
//  Listen(Sockets[0],SoMaxConn);
  ReadTimeVal.tv_sec:=5;
  ReadTimeVal.tv_usec:=0000;
  while True do
   begin
    // 1. ”®а¬Ёа®ў &shy;ЁҐ ¬&shy;®¦Ґбвў  б®ЄҐв®ў
      writeln('1 - FD_Zero = ”®а¬Ёа®ў &shy;ЁҐ ¬&shy;®¦Ґбвў  б®ЄҐв®ў');
    FD_Zero(FDReadSet);
    FD_Zero(FDWriteSet);
    FD_Zero(FDErrorSet);
    for I:=low(Sockets) to High(Sockets) do
    begin
     FD_Set(Sockets,FDReadSet);
     FD_Set(Sockets,FDWriteSet);
     FD_Set(Sockets,FDErrorSet);
    end;
    // 2. Џа®ўҐаЄ  Ј®в®ў&shy;®бвЁ б®ЄЄҐв
       writeln('2.B - Select = Џа®ўҐаЄ  Ј®в®ў&shy;®бв б®ЄЄҐв ');
    FDSetCount := Select(0,@FDReadSet,{@FDWriteSet,@FDErrorSet,}nil, nil, @ReadTimeVal);
      writeln('2.E');
    writeln('- = ',FDSetCount);
    if FDSetCount = Socket_Error then ShowError('Error', WSAGetLastError);
    if FDSetCount>0 then
     for I:=low(Sockets) to High(Sockets) do
     begin
      if FD_IsSet(Sockets,FDReadSet)
      then write(i,' ');
     end;
    readln;
   end;
 end.


Так вот на функции Select возвращается Socket_Error и ни как не меняет FDReadSet, при этом WSAGetLastError ни чего не возвращает.

В чём проблема?

Примечание : может конечно обратился не туда, пишу на FreePascal.

Зарание спасибо.
303
07 июня 2009 года
makbeth
1.0K / / 25.11.2004
Смущает получение указателей на параметры в вызове Select. Как вообще описана функция?
286
07 июня 2009 года
misha_turist
572 / / 28.11.2005
Цитата: makbeth
Смущает получение указателей на параметры в вызове Select. Как вообще описана функция?



Так и должно быть...

http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1021#11
Вот код примера из данной статьи

Код:
var Sockets:array of TSocket;
    Addr:TSockAddr;
    Data:TWSAData;
    Len,I,J:Integer;
    FDSet:TFDSet;
 begin
  WSAStartup($101,Data);
  SetLength(Sockets,1);
  Sockets[0]:=Socket(AF_Inet,Sock_Stream,0);
  Addr.sin_family:=AF_Inet;  Addr.sin_port:=HToNS(5514);
  Addr.sin_addr.S_addr:=InAddr_Any;  FillChar(Addr.Sin_Zero,SizeOf(Addr.Sin_Zero),0);
  Bind(Sockets[0],Addr,SizeOf(TSockAddr));
  Listen(Sockets[0],SoMaxConn);
  while True do   begin
    // 1. Формирование множества сокетов
    FD_Zero(FDSet);
    for I:=0 to High(Sockets) do
     FD_Set(Sockets,FDSet);
    // 2. Проверка готовности сокетов
    Select(0,@FDSet,nil,nil,nil);
    // 3. Чтение запросов клиентов тех сокетов, которые готовы к этому
    I:=1;
    while I<=High(Sockets) do
     begin
      if FD_IsSet(Sockets,FDSet) then
       if Recv(Sockets,…)<=0 then
        begin
         // Связь разорвана, надо закрыть сокет
         // и удалить его из массива
         CloseSocket(Sockets);
         for J:=I to High(Sockets)-1 do
          Sockets[J]:=Sockets[J+1];
         Dec(I);
         SetLength(Sockets,Length(Sockets)-1)
        end
       else
        begin
         // Поучены данные от клиента, надо ответить
         Send(Sockets,…)
        end;
      Inc(I)
     end;
    // 4. Проверка подключения нового клиента
    if FD_IsSet(Sockets[0],FDSet) then
     begin
      // Подключился новый клиент
      SetLength(Sockets,Length(Sockets)+1);
      Len:=SizeOf(TSockAddr);
      Sockets[High(Sockets)]:=Accept(Sockets[0],@Addr,@Len)
     end
   end;
288
08 июня 2009 года
nikitozz
1.2K / / 09.03.2007
А WSAGetLastError что возвращает?
14
09 июня 2009 года
Phodopus
3.3K / / 19.06.2008
А где сокеты-то сами создаются?
303
09 июня 2009 года
makbeth
1.0K / / 25.11.2004
В приведенном коде, здесь:
 
Код:
Sockets[0]:=socket(AF_INET,SOCK_STREAM,0{IPProto_TCP});
14
09 июня 2009 года
Phodopus
3.3K / / 19.06.2008
Ну я имею ввиду остальные-то, кроме 0-го. В массиве их 64, в сэте тоже (максимум) 64, первый то он создал а остальные добавил неинициализированными.
303
09 июня 2009 года
makbeth
1.0K / / 25.11.2004
Где??? Один создал (который [0]), только с ним и работает.

misha_turist, ты кстати, куда пропал? Разрулил проблему?
14
09 июня 2009 года
Phodopus
3.3K / / 19.06.2008
Цитата:

Где??? Один создал (который [0]), только с ним и работает.


тут

 
Код:
for I:=0 to High(Sockets) do
     FD_Set(Sockets,FDSet);
286
09 июня 2009 года
misha_turist
572 / / 28.11.2005
[COLOR=black][FONT=Verdana]Доброго времени суток![/FONT][/COLOR]

[COLOR=black][FONT=Verdana]Извините что так долго..[/FONT][/COLOR]


[COLOR=black][FONT=Verdana]Отвечаю по пунктам [/FONT][/COLOR]
  1. [COLOR=black][FONT=Verdana][quote=nikitozz]А WSAGetLastError что возвращает? [/quote] Функция WSAGetLastError возвращает код ошибки которая произошла т.е. если вы получили результат Socket_Error (читай "-1"), то это значит что что-то не так, а что именно не так можно узнать с помощью WSAGetLastError. [/FONT][/COLOR]
  2. [COLOR=black][FONT=Verdana]Проблема решена! и решена очень просто.. (кривые руки программиста голове покоя не дают ) [quote=Phodopus]...первый то он создал а остальные добавил неинициализированными. [/quote]. При заполнении множества сокетов
     
    Код:
    for I:=0 to High(Sockets) do FD_Set(Sockets,FDSet);
    в него добавляются ВСЕ дескрипторы из массива Sockets, НО ведь массив Sockets описан как массив фиксированной длины и совсем не обязательно, что в каждом из его элементов будет дескриптор инициализированного сокета. А что будет в неинициализированных элементах? Правильно - МУСОР. Вот на этом мусоре функция Select и ломалась... Так что решения два или переписать цикл как
     
    Код:
    for I:=low(Sockets) to low(Sockets)+connect_count-1 do FD_Set(Sockets,FDSet);
    или использовать динамические массивы как во [COLOR=#22229c]втором моём сообщении[/COLOR].[/FONT][/COLOR]
[COLOR=black][FONT=Verdana]Спасибо всем за участие. [/FONT][/COLOR]
303
09 июня 2009 года
makbeth
1.0K / / 25.11.2004
Блин... а в первом примере фиксированный массив я и не заметил... :( Предполагал, что там динамический...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог