LINUX.ORG.RU

[network] Посоветуйте чтива по организации потоко-безопасных протоколов

 


0

1

Точнее не потоко-безопасных, а конкурентных. То есть, интересует как реализуется клиент-серверный протокол, с которым можно работать из разных потоков через одно соединение.

    Thread1 --> conn.send(data1) --> conn.recv() // Reply for data1? 
    Thread2 --> conn.send(data2) --> conn.recv() // Reply for data2?

Или я хочу странных вещей и все просто открывают несколько соединений?

★★★

Последнее исправление: baverman (всего исправлений: 1)
Ответ на: комментарий от adzeitor

The term multi-streaming refers to the capability of SCTP to transmit several independent streams of chunks in parallel, for example transmitting web page images together with the web page text.

adzeitor
()

>потоко-безопасных
ну ты блин и завернул. тредсейф написал - все бы поняли.

fork_you
()
Ответ на: комментарий от anonymous

msgpack-rpc еще и zeromq

Если бы я хотел ковырять исходники, я бы просто так и сделал.

baverman ★★★
() автор топика

Контейнеры спасут:) Точнее инкапсуляция данных потока в некоторую сушность более высокого уровня(ну или более низкого, смотря как посмотреть. типичный подход:

+-----------------------------------------------------------------------------------------------------------------+
| parentID | body full size | subID1 | subLen1 | subLen1 bytes of data | subID2 | subLen2 | subLen2 bytes of data |
+-----------------------------------------------------------------------------------------------------------------+

Jetty ★★★★★
()
Ответ на: комментарий от Jetty

типичный подход:

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

baverman ★★★
() автор топика

Я обычно в таких случаях скрываю сокет в прокси со state machine. И потом работаю только с прокси. Прямая задача прокси - конкуренция. Может быть велосипед, других подобных решений не знаю, но думаю они есть.

mi_estas
()
Ответ на: комментарий от baverman

> когда один поток висит в блоке
Подожди, ты что собрался читать/писать из/в сокет из нескольких потоков в блокирующем режиме и без селекта(и ко) или отдельной «сетевой абстракции» ? Но зачем? Ну можно конечно мутексов нагородить, но зачем ? :)

Jetty ★★★★★
()
Ответ на: комментарий от mi_estas

Я обычно в таких случаях скрываю сокет в прокси со state machine.

Для моей задачи нужен будет полноценный eventloop на стороне клиента. Как-то слишком убийственно. Да и то, не знаю как красиво реализовать такой сценарий.

            |                          |
   msg_id = cl.put(message)            |
            |                          |
   cl.wait_for_ack(msg_id)             |
         (block)                       | 
            |                          |
            |                   msg_id = cl.get()
            |                          |
            |                    cl.ack(msg_id)
            |                          |
        (unblock)                      |
            |                          | 

Один поток кладет сообщение и ждет ответа. Второй поток сообщение получает и отвечает на него.

baverman ★★★
() автор топика
Ответ на: комментарий от Jetty

Подожди, ты что собрался читать/писать из/в сокет из нескольких потоков в блокирующем режиме и без селекта(и ко) или отдельной «сетевой абстракции» ?

Совершенно верно. Как раз самый нижний уровень и интересует.

Ну можно конечно мутексов нагородить, но зачем ? :)

Не вижу, чем здесь помогут мьютексы. Смотри диаграмму выше.

baverman ★★★
() автор топика
Ответ на: комментарий от baverman

Всё равно понадобится какой-то менеджер, читающий все сообщения, и освобождающий того клиента, которому получил ожидаемое msg_id. Наверное, это можно сделать через нить или yield.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Всё равно понадобится какой-то менеджер, читающий все сообщения, и освобождающий того клиента, которому получил ожидаемое msg_id.

Мозгом я понимаю, что по другому никак. Но как представишь, что надо сериализовать порядок сообщений на сервере/клиенте и быть предельно аккуратным, то как-то не вериться, то разработчики это каждый раз делают руками, да еще и на Сях.

baverman ★★★
() автор топика
Ответ на: комментарий от baverman

> как представишь, что надо сериализовать порядок сообщений на сервере/клиенте и быть предельно аккуратным, то как-то не вериться, то разработчики это каждый раз делают руками, да еще и на Сях.

А в чем проблема? Есть нить менеджера, которая только и имеет право читать/писать сокет, и у нее очереди входных и выходных сообщений. Вся сериализация/десериализация сосредоточены в одном месте. Правда, насчет «каждый раз» не понял.

Я так понимаю, ты хочешь SRR для нескольких клиентов/серверов поверх единого соединения?

tailgunner ★★★★★
()
Ответ на: комментарий от baverman

я моей т.з. если бы у тебя были потоки, а не процессы, то тебе надо было бы использовать какой-то ipc, ну а поскольку у тебя потоки то можно: либо использовать существующий ipc, либо навелосипедить свой, с мутексами, семафорами и condition_variables. вот конкретно для твоей схемы posix message queue подошел бы идеально. но он медленный говорят, но сам я его не тестировал на скорость, не знаю.

mi_estas
()
Ответ на: комментарий от mi_estas

ой, наоборот «если бы у тебя были процессы, а не потоки»

mi_estas
()

> Или я хочу странных вещей и все просто открывают несколько соединений?

Да

Harald ★★★★★
()
Ответ на: комментарий от tailgunner

ты хочешь SRR для нескольких клиентов/серверов поверх единого соединения?

Не знаю что такое SRR, гугол говорит что это поле в тисипишном пакете. Если так, то нет. Нужен конкурентный клиент (много клиентов, один сервер) через одно соединение. Желательно абстрагируясь от конкретного транспорта. Но это скорее для себя, текущее решение уже давно работает — просто открывает по соединению на каждый поток.

Интересует насколько возрастет сложность и можно ли сделать такую же эффективную (как в случае строго одного клиента на коннекшен) реализацию.

baverman ★★★
() автор топика
Ответ на: комментарий от baverman

>> ты хочешь SRR для нескольких клиентов/серверов поверх единого соединения?

Не знаю что такое SRR

Send-Receive-Reply. Можно считать, что это обобщенный RPC.

Интересует насколько возрастет сложность и можно ли сделать такую же эффективную (как в случае строго одного клиента на коннекшен) реализацию.

Я не вижу, почему нет. Разным видам RPC уже лет 30 (если тебе нужен именно RPC, то есть строго «запрос-ответ»).

tailgunner ★★★★★
()

если язык позволяет, то делаешь следующие легкие потоки:

1). берущий из канала новые сообщения канала запросов и пишущий их в сокет, при этом в канал приходит (message,place_where_result_should_be_put), вместо места куда положить результат можно передавать функцию (всё по вкусу). Данный поток присваивает сообщению номер и сохраняет у себя массив (msg_id, place). Так же может брать сообщение из канала ответов и класть по нужному адресу.

2). Поток тащащий данные из сокета и собирающий их в ответ и кладущий в канал ответов.

3..) твои потоки.

Впри желании 1,2 можно объединить, но мне было лень писал правда для com, а не для tcp, но суть та же, т.к. были конкурентные ответы.

могу пример на haskell скинуть ;)

qnikst ★★★★★
()
Ответ на: комментарий от baverman

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

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

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

Как оказалось, у меня нет понимания базовых вещей, как это должно происходить на самом верхнем уровне. Поэтому это упоминание было очень кстати.

baverman ★★★
() автор топика
Ответ на: комментарий от qnikst

на правах троллинга

все liftIO и монады опущены для упрощения понимания происходящего

inChan <- atomically newTChan
outChan <- atomically newTChan

forkIO $ withHandle (openHandle ...) $ \h -> do
    x<-atomically $ (readTChan inChan >>= return. Right) `orElse` (readTChan outChan >> return .Left) -- считать из одного из каналов, как только там будут сообщения
    case x of
       Left (m,p) -> do
            (c, t) <- get -- получить состояние counter и список ожидающих
            hPut h (put $ CountedMessage (c,m) )
            put (c+1, (c,p):t) --обновить counter и ожидающие
       Right (m,c) -> do
            (_,t) <- get 
             case lookup c t of
                 Just p -> putTMVar p m
                 Nothing -> return ()
             modify (\(x,y) -> (x, filter ((c/=).fst) -- обновили состояние
forkIO $ E.enumHandle h =? enumMessage $$ putToChan outChan
forkIO $ do
   x <- newTMVar 
   writeTChan inChan (MyMessage …)
   resp <- readTMVar  -- получить ответ тогда, когда появится

можно ещё и время ожидания ответа добавить

qnikst ★★★★★
()

Суть в том, чтобы несколько потоков юзали один сокет? Чтобы один блокировался в ожидании чтения данных для своего потока, а другой поток мог бы в это время что-то принимать/получать из того же сокета? Это ж можно завелосипедить за день, главное требования правильно составить.

yoghurt ★★★★★
()
Ответ на: комментарий от yoghurt

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

hatefu1_dead
()
Ответ на: комментарий от hatefu1_dead

Дык это и есть вариант реализации *задачи*, которую я в своём комменте пытался уяснить. Задачу от решения отличать умеем?

yoghurt ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.