информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Где водятся OGRыВсе любят медСтрашный баг в Windows
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Google заблокировала 2 с лишним... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Еще вопрос... может кто опытом поделиться ? 23.05.03 14:42  Число просмотров: 997
Автор: XR <eXtremal Research> Статус: The Elderman
<"чистая" ссылка>
> Необходимо определить количество дескрипторов в fd_set,
> после вызова select.
> Всю сознательную жизнь, в виндах, делал так:
>
> fd_set readfds;
> ...
> if( readfds.fd_count > 0 )


Об чем я и говорил :))

Winsock != *NIX socket API

> ...
>
> Ибо структура fd_set проста:
>

> typedef struct fd_set {
> u_int fd_count; /* how many are SET?
> */
> SOCKET fd_array[FD_SETSIZE]; /* an array of
> SOCKETs */
> } fd_set;
>
> [Черт меня дернул писать еще и под линух !]

Вот выдержка их man select

RETURN VALUE
On success, select and pselect return the number of descriptors
contained in the descriptor sets, ....
<programming>
[C++] Проблемма с select() (diff Win and *nix) 22.05.03 16:26  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
Под виндами все работает, под линухом - нет.
Суть проблеммы в том, что я помещаю сокеты установленные для прослушивания в readfds, под виндами (когда клиент коннектится к серверу) select возвращает эти сокеты и я делаю accept. Под линухом - они НЕ возвращаются ! При этом, всегда возвращается 0, т.е. как бы ни один сокет не дернут.
Есть еще одна странность - клиент ничего не говорит о том, что не может приконнектиться. Хотя accept на сервере сделать не могу (из-за описанной выше проблеммы).

"Совершенно не понятно - %опа есть, а слова нет".

Действительно select под линухом не возвращает сокеты установленые на листен, или это у меня проблемма ?

If the socket is currently in the listen state, it will be marked as readable if an incoming connection request has been received such that an accept is guaranteed to complete without blocking.
Это строчка из MSDN, в man я ничего аналогичного не нашел.

И второе, не могу догнать почему не ругается клиент :(

	while( !finishStatus )
	{
		fd_set readfds;
		fd_set writefds;
		fd_set exeptfds;

		FD_ZERO( &readfds );
		FD_ZERO( &writefds );
		FD_ZERO( &exeptfds );

		int readN  = SetFDRead( &readfds );
		int writeN = SetFDWrite( &writefds );
		int exeptN = SetFDExept( &exeptfds );

		int n = readN;
		if( n < writeN )
			n = writeN;
		if( n < exeptN )
			n = exeptN;
		
		tv.tv_sec = 5;
		tv.tv_usec= 0;

		printf( "Select n = %ld\n", n );
		int selRet = select( n, &readfds, &writefds, &exeptfds, &tv );

		if( selRet == SOCKET_ERROR )
		{
			int err;
#ifdef WIN32
			err = GetLastError();
#else
			err = errno;
#endif
			printf( "Error while select: %ld\n", err );
			return false;
		}

		if( selRet > 0 )
		{
			ProcFDRead( &readfds );
			ProcFDWrite( &writefds );
			ProcFDExept( &exeptfds );
		}
		else
		if( selRet == SOCKET_ERROR )
		{
			int err;
#ifdef WIN32
			err = GetLastError();
#else
			err = errno;
#endif
			printf( "Error while select (2): %ld\n", err );
		}
		else
		if( selRet == 0 )
		{
			printf( "Select timout... No sockets processing...\n" );
		}

		finishStatus = m_finish.Get();
	}

---
int TCPConnector2::SetFDRead( fd_set* read )
{
	int n = 0;
	FD_SET( m_listener_reader, read );
	n++;
	FD_SET( m_listener_writer, read );
	n++;
	for( int i  = 0; i < m_sockets.size(); i++ )
	{
		struct SocketPool* sp = m_sockets[i];
		if( sp->s_read != INVALID_SOCKET )
		{
			FD_SET( sp->s_read, read );
			n++;
		}
	}

	return n;
}

---
Еще вопрос... может кто опытом поделиться ? 23.05.03 12:30  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
Необходимо определить количество дескрипторов в fd_set, после вызова select.
Всю сознательную жизнь, в виндах, делал так:

fd_set readfds;
...
if( readfds.fd_count > 0 )
...

Ибо структура fd_set проста:
typedef struct fd_set {
        u_int fd_count;               /* how many are SET? */
        SOCKET  fd_array[FD_SETSIZE];   /* an array of SOCKETs */
} fd_set;

[Черт меня дернул писать еще и под линух !]

Под линухом мы имеем:
/* fd_set for select and pselect.  */
typedef struct
  {
    /* XPG4.2 requires this member name.  Otherwise avoid the name
       from the global namespace.  */
#ifdef __USE_XOPEN
    __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->fds_bits)
#else
    __fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];
# define __FDS_BITS(set) ((set)->__fds_bits)
#endif
  } fd_set;

---

Это что за порнография ?! И как мне из этой "структуры", прикажите достать количество дескрипторов ?

---
Еще вопрос... может кто опытом поделиться ? 23.05.03 14:42  
Автор: XR <eXtremal Research> Статус: The Elderman
<"чистая" ссылка>
> Необходимо определить количество дескрипторов в fd_set,
> после вызова select.
> Всю сознательную жизнь, в виндах, делал так:
>
> fd_set readfds;
> ...
> if( readfds.fd_count > 0 )


Об чем я и говорил :))

Winsock != *NIX socket API

> ...
>
> Ибо структура fd_set проста:
>

> typedef struct fd_set {
> u_int fd_count; /* how many are SET?
> */
> SOCKET fd_array[FD_SETSIZE]; /* an array of
> SOCKETs */
> } fd_set;
>
> [Черт меня дернул писать еще и под линух !]

Вот выдержка их man select

RETURN VALUE
On success, select and pselect return the number of descriptors
contained in the descriptor sets, ....
Массивов три, а return value - один ! 23.05.03 15:41  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
Вот в чем проблемма то...

Допустим есть код:
int selRet = select( n, &readfds, &writefds, &exeptfds, &tv );
..
		if( selRet > 0 )
		{
#ifdef WIN32
			if( readfds.fd_count > 0 )
#endif
				ProcFDRead( &readfds );

#ifdef WIN32
			if( writefds.fd_count > 0 )
#endif
				ProcFDWrite( &writefds );

#ifdef WIN32
			if( exeptfds.fd_count > 0 )
#endif
				ProcFDExept( &exeptfds );
		}

---

Так вот selRet мне ни о чем не говорит. С помощью него я только узнаю: 1. Есть ли хоть в одном из массивов что нибудь. 2. Не произошла ли ошибка.
А вот в каком из массивов у меня сколько - понятия не имею. Приходится просто так гонять цикл проверки ВСЕХ моих сокетов с помощью FD_ISSET во всех ТРЕХ функциях.
Ко всему прочему дело усугубляется прекрассным макросом:
# define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d))

#define __FD_SETSIZE 1024
typedef long int __fd_mask;
#define __NFDBITS (8 * sizeof (__fd_mask))
#define __FDELT(d) ((d) / __NFDBITS)
#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS))

__fd_mask __fds_bits[__FD_SETSIZE / __NFDBITS];

Т.е. размер fd_set = 1024 / (8*4) = 32 байта !!! Всего лишь !!!

Допустим я хочу проверить, существует ли дескриптор (-1) или (0xFFFFFFFF), что соответствует INVALID_SOCKET в видос, в моем fd_set.
Получаем: 0xFFFFFFFF / 32 = 0x07FFFFFF
(set)[0x07FFFFFF] при 32'ух возможных даст Segmentation fault, что прекрасно и наблюдается.
[C++] Проблемма с select() (diff Win and *nix) 22.05.03 16:43  
Автор: XR <eXtremal Research> Статус: The Elderman
<"чистая" ссылка>
Сходу по типичным ошибкам ....
> printf( "Select n = %ld\n", n );
> int selRet = select( n, &readfds,
> &writefds, &exeptfds, &tv );

n должен быть максимальный fd+1
(man select)

Вообще *NIX овый и Winsock-овый select-a это вещи довольно таки параллельные
- винсокоый был сделан для переносимости кода с *NIX - в обратную сторону перенос
может иметь множество косяков (хотя бы потому что сам дескриптор виньсока это совершенно иной объект нежели это имелось ввиду в *NIX)
Понял кстати :) 22.05.03 16:51  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
"n is the highest-numbered descriptor" ,был неправильно прочитан мной как "максимальное количество дескрипторов", вместо правильного "дескриптор с максимальным номером".
Отсюда и проблемма. Пойду перечитаю учебник английского :)

Переписал на:
int TCPConnector2::SetFDRead( fd_set* read )
{
	int n = m_listener_reader;
	FD_SET( m_listener_reader, read );	
	FD_SET( m_listener_writer, read );
	if( n < m_listener_writer )
		n = m_listener_writer;

	for( int i  = 0; i < m_sockets.size(); i++ )
	{
		struct SocketPool* sp = m_sockets[i];
		if( sp->s_read != INVALID_SOCKET )
		{
			FD_SET( sp->s_read, read );
			if( n < sp->s_read )
				n = sp->s_read;
		}
	}

	return n;
}

---

И все заработало.


> n должен быть максимальный fd+1
> (man select)
>
> Вообще *NIX овый и Winsock-овый select-a это вещи довольно
> таки параллельные
> - винсокоый был сделан для переносимости кода с *NIX - в
> обратную сторону перенос
> может иметь множество косяков (хотя бы потому что сам
> дескриптор виньсока это совершенно иной объект нежели это
> имелось ввиду в *NIX)

Ну тут должно быть все прозрачно (я верю в это :)) ).
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach