Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2005.07.31;
Скачать: [xml.tar.bz2];

Вниз

Проблема с send()/recv() в многопоточной программе   Найти похожие ветки 

 
Alexis ©   (2005-04-18 16:07) [0]

Добрый день!
Вообще-то пишу программу на C++ да еще и под Linux, но для прояснения "матчасти" обращаюсь сюда :)

Проблема такая-надо создать многопоточный сервер (клиент-серверных соединений TCP/IP, сокеты блокирующие).

Значица, создаю я на сервере сокет и начинаю его в цикле слушать и принимать подключившихся клиентов
while (1) {
  listen(servsock, MAX_QUEUE);
  clientsock = accept(servsock, ..., ...);
  //здесь создаю новый поток, в который передаю адрес выполняемой ф-ции и как параметр - дескриптор подключившегося клиента, после чего вновь начинаю слушать подключения на сервере
}

void *pthread_func(params)
{
//из параметров выдираю дескриптор клиента, и в цикле его слушаю
  while(1) {
     bytesRecv = recv(clientsock, ...);
     if (bytesRecv <= 0)
     {
        //клиент отсоединился, мои действия, break;
     }
     ...
  }
}

Но вот в чем беда-при нажатии на кнопку сервер должен разослать всем клиентам некое текстовое сообщение(дескрипторы клиентов он хранит в контейнере), но во всех созданных сервером потоках выполнение приостановлено на recv(), т.е. сокеты ждут поступления данных, а в них пытаются записать send()"ом!
Как в таком случае поступать, если схема работы сервера "получил данные-отослал ответ-ждешь-получил данные " не пригодна?

Заранее огромное спасибо.


 
Digitman ©   (2005-04-18 16:10) [1]

см. select()


 
Alexis ©   (2005-04-18 16:17) [2]


> Digitman ©   (18.04.05 16:10) [1]
> см. select()

Да, спасибо, уже смотрел. Но как я понял select() только "констатирует факт", что такой-то сокет готов к приему, такой-то готов к отсылке, но не может менять их состояния. Т.е. если поток приостановлен send()"ом, то select() скажет, что сокет готов к приему, но не готов к отсылке, но мне это и так известно.
Или я не прав?


 
Polevi ©   (2005-04-18 16:29) [3]

отлельный канал делай для служебных команд


 
Digitman ©   (2005-04-18 16:31) [4]


> select()


select() действительно "констатирует факт", но не для "такого-то" сокета, а для конкретно указанного тобой

если тебя интересует факт готовности, например, к приему, ты вызываешь select() с небольшим тайм-аутом ожидания, и если ф-ция вернула сей достоверный факт, ты тут же вызываешь ф-цию recv(), которая вернет тебе все что доступно в буфере приема (но не более запрошенного), и произойдет это практически мгновенно (безо всякого ожидания, ибо буфер приема по факту заведомо не пуст), после чего ты способен тут же прореагировать на сообщения своему трансп.трэду


 
Alexis ©   (2005-04-18 17:44) [5]

Sorry za translit.
.........
если тебя интересует факт готовности, например, к приему, ты вызываешь select() с небольшим тайм-аутом ожидания, и если ф-ция вернула сей достоверный факт, ты тут же вызываешь ф-цию recv()
.........
T.e. select() neobhodimo ispolzovat v thread"e, obsluzivajushem konkretnogo klienta. Ili select() sposobna sledit" za neskolkimi klientami i thread"ov voobshe ispolzovat ne nado?

>с небольшим тайм-аутом ожидания
Kakoj time-out nebolshoj? I voobshe on nuzen dlia blokirovanija f-ciji select() na eto vremia?


 
atruhin ©   (2005-04-19 07:24) [6]

После вызова accept, пересылаешь клиенту данные, дальше вызываешь select, таймаут зависит от соединения и скорости обработки запроса клиентом, например для HTTP протокола в условиях интернета до 15 сек, если локальная сеть, и запрос обрабатывается быстро, таймаут может быть 1-2 сек. далее если select завершился по таймату, в зависимости от задачи, либо можешь послать следующий запрос, либо завершить поток.


 
Polevi ©   (2005-04-19 09:02) [7]

не будет это работать в реальной жизни


 
Ozone ©   (2005-04-19 11:30) [8]

Мое ИМХО, откажись от блокирующих сокетов (а следовательно и потоков) и уйди полностью в сторону select (как уже подсказал Digitman).


 
Digitman ©   (2005-04-19 11:34) [9]


> Ozone ©   (19.04.05 11:30) [8]


тогда уж наоборот - НЕблокирующий режим и безо всяких select()
а select() будет уместен как раз при блокирующем режиме


 
Ozone ©   (2005-04-19 11:37) [10]

>  [9] Digitman ©   (19.04.05 11:34)

Нет, Вы не правы, select() не будет работать с блокирующими сокетами.


 
Digitman ©   (2005-04-19 12:11) [11]


> Ozone ©   (19.04.05 11:37) [10]


с какого перепугу-то ?
цитируй документацию ...


 
Ozone ©   (2005-04-19 12:32) [12]

> [11] Digitman ©   (19.04.05 12:11)

Хмм... на самом деле, может быть я не прав. Даже так - я совсем не прав. Оно работать будет, но точно также (т.е. логика и ход выполнения программы не измениться) как и с неблокирующими.


 
Digitman ©   (2005-04-19 12:44) [13]


> Ozone ©   (19.04.05 12:32) [12]


вот именно


 
nikkie ©   (2005-04-19 16:21) [14]

я извиняюсь - откуда неблокирующие сокеты под linux?


 
Alexis ©   (2005-04-19 19:06) [15]


> nikkie ©   (19.04.05 16:21) [14]
> я извиняюсь - откуда неблокирующие сокеты под linux?

Ottuda ze, otkuda i v Windows :)

Gospoda! Vsem spasibo za pomosh", no delo okazalos sovsem v drugom :) Prosto ja ne vydelil pamiat" pod char *buffer kotoryj peredaval kak parametr recv()
C - kovarnyj jazyk :)


 
nikkie ©   (2005-04-19 19:25) [16]

>Ottuda ze, otkuda i v Windows :)
микрософт написал?? :))

http://www.swissdelphicenter.ch/en/showarticle.php?id=4

In reality, blocking sockets are the ONLY way Unix does sockets. <..> Some extensions have been added for non-blocking sockets in Unix. However they work quite differently than in Windows. They also are not standard, and not in wide use. Blocking sockets under Unix still are used in almost every case, and will continue to be so.


 
Verg ©   (2005-04-19 20:32) [17]


> nikkie ©   (19.04.05 16:21) [14]
> я извиняюсь - откуда неблокирующие сокеты под linux?


Как ответить-то по-корректнее...? :))

см. FIONBIO -на самой заре TCP/IP, еще и линуксом-то не пахло, а уже был EWOULDBLOCK....

Или ты путаешь с асинхронным режимом? Который реализуются через неблокирующий режим+отдельный поток + всякие hwnd, postmessage и проч.


> C - kovarnyj jazyk :)


Delphi - не менее "коварен". И даже Васик - тот еще "перец"...


 
nikkie ©   (2005-04-19 21:07) [18]

путаю-путаю. наверное потому, что Kudzu использовал термин блокирующий как синоним синхронного. засело крепко.



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2005.07.31;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.066 c
14-1120817921
DeepProg
2005-07-08 14:18
2005.07.31
Непонятная AV


14-1120769650
Soft
2005-07-08 00:54
2005.07.31
С каким визуальным образом у вас ассоциируются.


1-1121065795
Курдль
2005-07-11 11:09
2005.07.31
Про отображение BLOB типа jpeg в DBImage


6-1113992960
zorik
2005-04-20 14:29
2005.07.31
Как узнать значение параметра (cgi-приложение)


6-1113844381
ALex B.
2005-04-18 21:13
2005.07.31
Как узнать какой доступ к шаре(под паролем, полный доступ)?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский