Доступ к сокету из нескольких Task. Мультисессия

10 views
Skip to first unread message

er ty

unread,
Nov 24, 2017, 3:32:32 PM11/24/17
to uOS embedded
Здравствуйте!

Подскажите пожалуйста, каким образом реализовать асинхронную запись в один и тот же открытый сокет из различных задач(нескольких)?
Возможно ли это в данной ОС?

Необходимо одновременно обрабатывать комманды пользователя, по (непредсказуемым)прерываниям отправлять
сообщение и закрывать сокет если нет активности n-секунд

Например запускается задача 1, в цикле которой вызываются функции: tcp_read(чтение из сокета), com_interpret(обработка пакета), tcp_write(отправка ответа).
Далее запускается задача 2: прикрепляется прерывание к мутексу mutex_attach_irq(вход внешнего прерывания), далее в бесконечном цикле ожидаем прерывания (mutex_wait) и отправляем информацию о прерывании в тот же сокет через tcp_write.
Запуск задачи-монитора для закрытия соединения по таймауту.

Код:

void tcp_task1 (){

    lsock
= tcp_listen (&ip, 0, serv_port);

   
for (;;) {

        user_socket
= tcp_accept (lsock);

           
for (;;) {
               tcp_read
(user_socket,...);
               com_interpret
(...);
               tcp_write
(user_socket,...);
           
}
   
}
close
:
......
}    

void tcp_task1 (void *data){

    mutex_attach_irq
(&ext_lock, EXT_IRQ_DEF, (handler_t)ext0_handler, 0);

   
for (;;) {
        mutex_wait
(&ext_lock);
       
if(user_socket){
            tcp_write
(user_socket,...);
       
}
   
}
close
:
......      
}

void tcp_act_mon (void){

   
for (;;) {
       
if (user_socket)){
           
if (tcp_inactivity (user_socket) > n) {
                tcp_close
(user_socket);      
           
}  
       
}
    timer_delay
(&timer, 1000);
   
}
}



Каким образом определить активность, защищать от одновременного доступа, закрывать, записывать и освобождать память сокета?
Существуют рабочие решения?

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

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

Код:

void task_server (void *data){ // задача слушает порт и при подключении создает задачу для приема пакетов

    lsock
= tcp_listen (&ip, 0, serv_port);

   
for (;;) {
        sock
= tcp_accept (lsock);
        task_create
(task_tcp_request, &tcp_slots[n], "task_tcp_request", 60, tcp_slots[n].stack_task_req, 1000);
   
}
}

void task_tcp_answer (void *arg){ //задача для отсылки сообщений

   
for (;;) {
        slot_msg
= (slots_t *) mutex_wait (&lock_answer); // можно сигналить из любой задачи?
          tcp_write
(slot_msg->sock, slot_msg->str_val, slot_msg->int_val);
   
}
}

void task_tcp_request (void *arg)
{
    slots_t
*slot_msg = (slots_t*) arg;

   
for (;;) {
        n
= tcp_read (slot_msg->sock, buff, 200); // получаем данные
        com_interpret
(...); // обрабатываем, может запустить отдельную задачу, которая через время выдаст
                               
//результат для отправки через mutex_signal (&lock_answer...);
        mutex_signal
(&lock_answer, slot_msg); // шлем сигнал задаче task_tcp_answer для отправке ответа
   
}
closed_req
:
   
...
   
...
   
...
task_exit
(0);
}

void task_tcp_act_mon (void *arg) { // отслеживание неактивных соединений
...
   
for (;;) {
       
for (n=0; n<MAXSESS; n++){
               
if (tcp_inactivity (tcp_slots[n].sock) > eth_timeout) { // перебираем все сокеты и закрываем если таймаут
                     tcp_close
(tcp_slots[n].sock);    
               
}      
       
}
        timer_delay
(&timer, 1000);
   
}
}




В примере выше имеется задача-отправитель (task_tcp_answer), которая ждет сигнала мутека.
В качестве сообщения передается указатель на структуру, содержащую указатели на сокет, буфер с данными и размер буфера для передачи.
Задачи (task_tcp_request) просто принимают данные, отдают интерпретатору команд, который сигналит мутексом со структурой описанной выше.
Задача монитор перебирает все сокеты и закрывает с истекшим временем ожидания.
Этот пример рабочий. Но иногда наблюдаются аномалии - не все сигналы мутексов отрабатываются, при интенсивной работе подтормаживает. Хитрой комбинацией открытия и закрытия соединения может упасть все - было один раз за тысячу тестов.
Пример с телнетом несовсем подходит, так как нужно параллельно принимать комманды из сокета, запускать задачи вычисления и выдавать в сокет результат асинхронно.
Реализовывал кто-нибудь подобное?

Reply all
Reply to author
Forward
0 new messages