Автор Тема: Ошибка в коде  (Прочитано 8313 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн ZMeY

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 54
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Ошибка в коде
« : 25 Февраля 2004, 15:11:32 »
код:


use IO::Socket;
use 
IO::Select;
use 
HTTP::Daemon;
use 
POSIX

use 
Fcntl;

$|=
1;

$port 5555;
$max_clients 35#SOMAXCONN

%logon =();
%
nick =();
%
SID =();
%
log_time =();
%
perms =();
%
IP=();

$server HTTP::Daemon->new(Proto => \'tcp\', LocalPort => $port, Listen => $max_clients) or die "Can\'t make server socket: $@\\n";
nonblock($server);
$select = IO::Select->new($server);


print "[Chat server runing on ", $server->url, "] \\n\\n";



while (1)
{
	
foreach $client ($select->can_read(1))
	
{
	
	
if ($client == $server)
	
	
{
	
	
#обработка событий подключения
	
	
my $new_client = $server->accept();
	
	
	
if(defined($new_client))
	
	
	
{
	
	
	
print "Client accepted\\n";
	
	
	
nonblock($new_client);
	
	
	
$select->add($new_client);
	
	
	
$logon{$new_client}="";
	
	
	
$nick{$new_client}="";
	
	
	
#присвоение остальных переменных
	
	
	
}
	
	
}
	
	
else
	
	
{
	
	
my $data = \'\'; 
	
	
my $rv = $client->recv($data, POSIX::BUFSIZ, 0); 
	
	
unless (defined($rv) && length $data)
	
	

	
	
	
#очистка переменных
	
	
	
#delete $inbuffer{$client};
	
	
	
#delete $outbuffer{$client};
	
	
	
#delete $ready{$client};
	
	
	
$select->remove($cllent);
	
	
	
delete $client; 
	
	
	
print "Client closed\\n";
	
	
	
next;
	
	

	
	
else
	
	
{
	
	
my $request = $client->get_request();
	
	
if (defined($request))
	
	
	
{
	
	

	
	
        if ($request->method eq \'GET\')
	
	
	
	
{
	
	
	
	
#обработка $Id.html
	
	
	
        }
	
	
	
 
	
else
	
	
	
	
{
	
	
	
	
#выдать сообщение о неверном запросе и записать в лог ошибку.
	
	
	
        }
	
	
	
}
	
	
}
	
	
}
	
}
}



sub nonblock { 
     my $sock = shift; 

     if ($^O eq \'MSWin32\')
     {
           sub FIONBIO { 0x8004667e } 
           my $set_it = "1"; 
           ioctl($sock, FIONBIO, $set_it) 
                 or die "Can\'t set the socket non-blocking: $!"; 
     } else { 
           my $flags = fcntl($sock, F_GETFL, 0) 
                 or die "fcntl fails with F_GETFL: $!"; 
           fcntl($sock, F_SETFL, $flags | O_NONBLOCK) 
                 or die "fcntl fails with F_SETFL: $!"; 
     } 



Эта прога - многопотоковый сервер, который акцептит клиентов и держит связь с ними.
Если какой-то клиент отключается срабатывает болк unless (defined($rv) && length $data) НО дальше идёт глюк - все последующие подключения акцептятся, но не обрабатываются, то есть $new_client - undefined, НО и ошибки не происходит и клиент сообщает об удачном коннекте.

Если убрать unless (defined($rv) && length $data) - всё работает нормально (но обрабатывать дисконнекты - обязательно) Как быть?
« Последнее редактирование: 25 Февраля 2004, 20:17:51 от NeoNox »

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
Ошибка в коде
« Ответ #1 : 25 Февраля 2004, 16:24:03 »
наверное нужно убрать ошибки сначала?
Что это за строки?
$select->remove($cllent);
delete $client;
The documentations is your friend

Оффлайн ZMeY

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 54
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Ошибка в коде
« Ответ #2 : 25 Февраля 2004, 19:43:17 »
NeoNox
foreach $client ($select->can_read(1)) - $client это элемент селекта
Нельзя же до бесконечности увеличивать селект - надо удалять неиспользованные элементыселекта

delete $client; - ошибка...следует читать close($client)

проблема в том, что my $new_client = $server->accept(); - действие совершается, но не возвращается сообщения о том, что оно совершено!

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
Ошибка в коде
« Ответ #3 : 25 Февраля 2004, 20:14:25 »
поставь use strict и убери все ошибки в этом коде - потом будем разбираться
The documentations is your friend

Оффлайн ZMeY

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 54
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Ошибка в коде
« Ответ #4 : 25 Февраля 2004, 20:25:19 »
[moderator ]
Здесь был код с ошибками.
[\\moderator ]


вот рабочая версия...
а нельзя ли как-то определить оборвавшегося клиента кроме, как строчками

      my $data = \'\';
      my $rv = $client->recv($data, POSIX::BUFSIZ, 0);
      unless (defined($rv) && length $data)
      {
....
а то без них - всё работает...да и у меня такое подозрение, что они и get_request обнуляют...
« Последнее редактирование: 26 Февраля 2004, 10:58:15 от NeoNox »

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
Ошибка в коде
« Ответ #5 : 26 Февраля 2004, 11:06:29 »
ZMeY я не понимаю кому это нужно - тебе или мне?
1) Код без use strict в начале скрипта рассматриваться больше не будет.
2) исправь опечатку в $select->remove($cllent);
3) что ты вкладываеш в понятие обрабатывать дисконекты? Кем, сервером или тобой?
The documentations is your friend

Оффлайн ZMeY

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 54
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Ошибка в коде
« Ответ #6 : 26 Февраля 2004, 14:39:40 »
исправь опечатку в $select->remove($cllent); - это не ошибка, а спецально написанная строка - ужаляет ненужный экземпляр массива select сокетов..а что в этой строке не так?

Оффлайн КшЫуфксрук

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 99
  • +0/-0
  • 0
    • Просмотр профиля
    • http://risearch.org/
Ошибка в коде
« Ответ #7 : 26 Февраля 2004, 16:30:13 »
> а что в этой строке не так?

Вот именно поэтому тебя и просят поставить strict и проверить весь код на отсутствие опечаток. А потом можно будет алгоритмом заняться.

Оффлайн mike

  • ProPerl\'er
  • Старожил
  • ****
  • Сообщений: 435
  • +0/-0
  • 2
    • Просмотр профиля
    • http://
Ошибка в коде
« Ответ #8 : 26 Февраля 2004, 16:30:48 »
Цитировать
ZMeY:
а что в этой строке не так?

Просто опечатка. Думаю, поймешь где и в чем собственно дело, когда начнешь использовать use strict;.
[ основной браузер когда-то был, теперь попробуй разберись =]

Оффлайн ZMeY

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 54
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Ошибка в коде
« Ответ #9 : 26 Февраля 2004, 19:41:13 »
ошибку я нашёл - скрипт работает прекрасно..но одно НО - чисто алгоритмическое.
Я определяю, что клиент "умер" по:
       my $rv = $client->recv($data, POSIX::BUFSIZ, 0);
        unless (defined($rv) && length $data)
но после этого вызывать
request - бессмысленно recv всё забирает...как по другому определить статус сокета, что бы и овцы сыты и волки целы то есть что бы и реквест получать и вовремя узнавать о "падении" клиента?

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
Ошибка в коде
« Ответ #10 : 26 Февраля 2004, 19:55:12 »
Ты исправил код и вставил use strict?
Замени его тогда в первом сообщении.
The documentations is your friend

Оффлайн ZMeY

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 54
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Ошибка в коде
« Ответ #11 : 26 Февраля 2004, 20:02:57 »
да я уже снял старый вопрос новый:
как определить дисконнект сокета, не используя чтение буфера?

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
Ошибка в коде
« Ответ #12 : 27 Февраля 2004, 01:07:41 »
А я еще не снял старый вопрос.
Тебе шашечки или ехать? Если шашечки то тебе в форум по изготовлению скриптов. Если ехать - отвечай на вопросы.
На данном этапе я хочу увидеть рабочий код.
Вторым я тебя спрошу про эти строки:
        my $data = \'\';
        my $rv = $client->recv($data, POSIX::BUFSIZ, 0);
        unless (defined($rv) && length $data)
и хочу узнать нафига тебе unless если length $data всегда равен 0?
Ты понимаеш что вообще происходит в этом коде?
The documentations is your friend

Оффлайн ZMeY

  • Завсегдатай
  • Пользователь
  • **
  • Сообщений: 54
  • +0/-0
  • 0
    • Просмотр профиля
    • http://
Ошибка в коде
« Ответ #13 : 27 Февраля 2004, 06:57:49 »
Цитировать

Вторым я тебя спрошу про эти строки:
my $data = \'\';
my $rv = $client->recv($data, POSIX::BUFSIZ, 0);
unless (defined($rv) && length $data)
и хочу узнать нафига тебе unless если length $data всегда равен 0?
Ты понимаеш что вообще происходит в этом коде?

Этот код на одном из форумов подсказали как код определения статуса скрипта. Если возвратит значение - сокет работает, если undefined - не работает. Этот код действительно чётко определяет, когда клиент отключился, НО. Он делает не возможным использование request . Я хочу заменить этот участок другим, который возвратит лож, если клиент отключился и истину, если клиент всё-ещё на связи. И  length $data  не всегда равна 0 т.к. recv($data...Хотя честно говоря этот участок мне мало понятен. Поэтому я хочу его заменить.

Оффлайн NeoNox

  • Координатор
  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 3012
  • +0/-0
  • 0
    • Просмотр профиля
Ошибка в коде
« Ответ #14 : 27 Февраля 2004, 13:27:34 »
Вот мне интересно почему тебе на том форуме не показали как \'это\' заставить работать? Мастера блин...
Замени блок на
unless (defined($rv) && length $data) {
 disconnect($client);
 next;
}

И что за else там стоит после unless?

Значит так, или я тебе даю рабочий код чата под nix и эту тему к чертям закрываю, либо ты пишеш сюда код с комментариями что каждая строка делает в цикле while(1). Выбирай.
The documentations is your friend

 

Sitemap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28