Jump to content
Форум по продукции MOXA

tcp2com IA240 проброска трафика тсп-порта в com-порт


Recommended Posts

Здравствуйте!

Очень необходим стабильный код программы проброски трафика тсп-порта в ком порт IA240 под UNIX.

Во вложении рабочий вариант (исходник, конф-файл и скомпилированный файл). При длительной работе этого варианта периодически образуются нерабочие окна минут в 20-40.... При прочих модификациях наблюдались полные зависания приложения :(.

 

Прошу помощи у специалистов! Пожалуйста, укажите ошибку или поделитесь стабильным рабочим кодом проброски трафика. Готов проспонировать 300-500 рублей на пиво при условии стаблильной работы вашего кода более суток.

 

Условия обмена по трафику:

1. Запросы сверху-вниз. Т.е. открывается ТСП-сокет, из него приходит запрос и транслируется в порт. Из порта должен прийти ответ в течении 1-4 сек. макисмум и отправлен обратно в tcp-порт. (Если не пришел, то ждать ответа дольше смысла нет).

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

3. Пакеты по обмену небольшие. В большинстве случаев укладываются в 255 - 300 байт.

 

Жду с нетерпением любой помощи. Заранее благодарю за советы.

АТК-tcp2ComIA240.zip

Link to comment

Здравствуйте!

 

Я, к сожалению, не силен проверять коды, но хочу просто обратить внимание на грамотные примеры программ, расположенные на подсайте rcorecommunity.moxa.com. Есть пример простейшего TCP-сервера, есть пример работы с COM-портом.

Может быть, просто попробовать их объединить, и получится всё здорово?

Link to comment

Здравствуйте!

Спасибо за ссылку. Но похоже это тоже самое что и на диске в комплекте с моксой....

Дело в том, что с этого все начиналось... Стандартные примеры очень похожи, но не подходят. Например, в одном из примеров направление связи из ком в тсп порт - по инициативе из ком-порта... Я тоже вначале думал, что достаточно изменить пару строк и скомплировать.

Я работал с внешним программистом который уже не один год кодит под моксу, он мне составил код из предыдущего топика. Но испытания показали, что он не стабильно работает. Стабилизировать его у него не получается. Предыдущие попытки и навороты приводили к зависанию приложения через некоторое время работы. Вот и прошу помощи у спецов в такой простой задаче. Блин.

Помогите, программисты. Если вопрос на столько сложен, что требует оплаты, пишите свои пожелания на web2reg[cобака]ya.ru.

Вообще, считаю, что такой функционал должен быть достоянием общественности и подготовлен спецами Моксы...

Заранее благодарю за ответ.

Link to comment

Насчет достояния общественности - очень спорный вопрос.

Код поглядел. причину предполагаю - скажите вам использования TCP протокола принципиально или его можно на UDP заменить.

Ибо причина подвисаний скорее всего в таймаутах на закрытие и открытие соединений по TCP, а в этой прожке при любом сбое на чтение или запись портов serial & lan происходит закрытие всех портов и потом по новой открываются.

Вариантов два:

1. менять TCP на UDP

2. продумать какая нужна реакция на ошибки чтения/записи

- я бы оба варианта применил.

 

P.S. или вообще pipe использовать....

Link to comment

Еще мысль возникла.

Если у Вас это единичный экземпляр то ладно.

Но если это тиражируемое решение по организации обмена с цифровыми устройствами, - то Вы используете не те решения.

Необходимый вам функционал реализуют NPortы, они открывают TCP-порты, которые ассоциируются с serial портами и гоняют между ними трафик. Т.е. драйвера которые дают com-порты в винде ставить не обязательно, ибо драйвера только открывают TCP соединения, и пропускают трафик через себя.

Понятно, что NPort по сути это Plug&Play устройства не требующего никакого стороннего софта, а только настройку режимов работы через web-морду.

Если все же нужен именно встраиваемый контроллер то пишите в личку, чего надо с софтинкой помогу.

Link to comment
  • 3 weeks later...

boneskos,

не знаю, насколько сильно помогу, но по моему опыту работы с COM-портами (под виндой пока), как раз с RS-485 2 wire, одиночного чтения из порта не достаточно. Иногда, функция чтения из порта не выдает весь кусок данных, который туда пришел/идет.

Читать из порта нужно до тех пор, пока не придет необходимый объем данных или не наступит таймаут.

В вашем же примере, чтение производится один раз, затем в следующем цикле снова идет запись, при этом где гарантия, что все данные от устройства выбрались чтением? В недуплексном канале обмена, коим является RS-485, записью в порт вы заставляете порт переключиться в режим передачи, а это может оказаться еще рано, возможно он еще принимает данные.

И еще: Вы вызываете функцию чтения из сом-порта сразу после записи, при этом flow control у вас отключен. В этом случае, на мой взляд, функцию чтения можно вызывать только по прошествию паузы, достаточной для отправки Вашего объема данных через сом-порт на данной скорости или после проверки того факта, что буфер передачи опустошился (не подскажу как сделать это в линуксе).

Link to comment
  • 2 years later...

Здравствуйте!

Очень необходим стабильный код программы проброски трафика тсп-порта в ком порт IA240 под UNIX.

Во вложении рабочий вариант (исходник, конф-файл и скомпилированный файл). При длительной работе этого варианта периодически образуются нерабочие окна минут в 20-40.... При прочих модификациях наблюдались полные зависания приложения :(.

 

Прошу помощи у специалистов! Пожалуйста, укажите ошибку или поделитесь стабильным рабочим кодом проброски трафика. Готов проспонировать 300-500 рублей на пиво при условии стаблильной работы вашего кода более суток.

 

Условия обмена по трафику:

1. Запросы сверху-вниз. Т.е. открывается ТСП-сокет, из него приходит запрос и транслируется в порт. Из порта должен прийти ответ в течении 1-4 сек. макисмум и отправлен обратно в tcp-порт. (Если не пришел, то ждать ответа дольше смысла нет).

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

3. Пакеты по обмену небольшие. В большинстве случаев укладываются в 255 - 300 байт.

 

Жду с нетерпением любой помощи. Заранее благодарю за советы.

 

Простите, но я не увидел в приложеннм коде формирования второго потока для работы со вторым соединением по TCP.

int do_it()
{
    char *ip;
    int size, rz, len;
    struct sockaddr_in client;
    struct timeval twait;
    fd_set ListenSockets;


    size = sizeof(client);

    while(1) {
        printf("accept...\n");

        sClient = accept(sListen, (struct sockaddr *)&client, &size);
        if (sClient < 0){
            print_err_mess("accept...failed");
            break;
        }

        ip = inet_ntoa(client.sin_addr);
        if (!ip)
            continue;


        sprintf(&sbuf[0], "connect from %s", ip);
        print_mess(&sbuf[0]);

        endtime_session = time(NULL) + cfg.max_time_session_min * 60;


        // set socket to nonblock
        rz = fcntl(sClient, F_GETFL);
        rz |= O_NONBLOCK;
        if (fcntl(sClient, F_SETFL, rz) < 0) {
            print_err_mess("set socket to nonblock fail");
            break;
        }

        while(1) {
            if (time(NULL) > endtime_session) {
                print_mess("session end time");
                return 2;
            }


            FD_ZERO(&ListenSockets);
            FD_SET(sClient, &ListenSockets);
            twait.tv_sec = 0;
            twait.tv_usec = 100;

            rz = select(sClient+1, &ListenSockets, NULL, NULL, &twait);
            if (rz < 0) {
                close_fd(&sClient);
                break;
            }
            else
            if (!rz || !FD_ISSET(sClient, &ListenSockets)) {
                 //nothing receive
            }
            else {
                // receive data form LAN
                rz = recv(sClient, rbuf, BUFFER_LEN, 0);
                if (!rz){
                    printf("LAN: recvice 0 bytes (!)\n");
                    close_fd(&sClient);
                    break;
                }
                else if (rz < 0) {
                    if (errno == EAGAIN) {
                        /* The socket is marked non-blocking, and the receive
                         operation would block, or a receive timeout had been set,
                         and the timeout expired before data were received. */
                        continue;
                    }
                    if (errno == ENOTCONN) {
                        /* The socket is associated with a connection-oriented protocol
                        and has not been connected */
                        close_fd(&sClient);
                        break;
                    }
                    close_fd(&sClient);

                    print_mess("LAN disconnected");

                    printf("\n");
                    break;
                }


                if (cfg.log) {
                    if (cfg.log == 2)
                        printf("LAN: read %d bytes\n", rz);
                    if (cfg.log > 2)
                        PrintBytes(rbuf, rz);
                }

                // write data to serial port
                len = write(fd, rbuf, rz);
                if (len < 0) {
                    print_err_mess("COM: write fail");
                    return -1;
                }
            }

            // read data from serial port
            len = read(fd, sbuf, BUFFER_LEN);
            if (len < 0) {
                print_err_mess("COM: read data fail");
                return -1;
            }
            else
            if (len > 0) {
                if (cfg.log) {
                    if (cfg.log == 2)
                        printf("COM: read %d bytes\n", len);
                    if (cfg.log > 2)
                        PrintBytes(sbuf, len);
                }

                // send data to LAN
                rz = send(sClient, sbuf, len, 0);
                if(rz < 0){
                    print_err_mess("LAN: send data fail");
                    return -1;
                }
            }

        }
    }

    return 0;
}

Так, что обрабатывать второй сокет некому! Так что после приёма соединения необходимо открывать "параллельный" поток для обработки текущего соединения

для sClient = accept(sListen, (struct sockaddr *)&client, &size);

, а этот цикл адаптировать для ожидания другого sClient = accept(sListen, (struct sockaddr *)&client, &size);

далее для которого будет открыт свой поток.

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...