powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Сокеты в си
18 сообщений из 43, страница 2 из 2
Сокеты в си
    #39088151
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
t111кДа если передающая сторона будет отсылать EOF можно было бы его ловить, но наверно передающая сторона и не посылает его
rc=read(sock, &ch, 1);
Когда rc == 0 это и есть EOF.
Если rc < 0 это ошибки всякие.

Касательно чтения когда длина известна. Напишите функцию read_all() которая принимает те же параметры но читает ровно заданное кол-во байтов (в цикле).
Такой функцией намного удобнее и проще пользоваться чем вводить явные циклы в алгоритм, который по сути линейный.
...
Рейтинг: 0 / 0
Сокеты в си
    #39088278
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
t111кДа спасибо. Да действительно, если я только знаю сколько байт приходит в одном пакете первые 4 байта пакета (204 байт), попробую только по одному пакету принимать и обрабатывать.
Все таки размер приходит?

Если так, то ты слишком много написал лишнего. Не надо высшей математики, можно так
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
int chetbiet,nomerbite,nomzapbite, kolbite,r1blok1,i1,c,totalcnt ;
while (1) {
   rc=recv(sock, buf_lin2, 4,0);
   if (rc<=0) break;
   memcpy(&kolbite, buf_lin2, 4);
   if (kolbite > sizeof(buf_lin2) - 4) {
      printf("Недостаточный размер буфера\n");
      break;
   }
   totalcnt = 0;
   while(totalcnt < kolbite) {
       rc=recv(sock, &buf_lin2[4+totalcnt], kolbite - totalcnt, 0);
       if (rc<=0) break;
       totalcnt += rc;
   }
   if (rc<=0) break;
   obrabwialonretr(buf_lin2, sock);
}
if(rc<=0) printf("Сервер не прочитал\n");



PS В коде отступы не забывай делать. Читать невозможно.
...
Рейтинг: 0 / 0
Сокеты в си
    #39088320
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лучше все в одном цикле читать. Возможно что 4 байта размера не придут вместе, тогда твой и мой предыдущий вариант сглючат.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
int chetbiet,nomerbite,nomzapbite, kolbite,r1blok1,i1,c,totalcnt ;
while (1) {
   totalcnt = 0;
   kolbite = 4; // сначала читаем размер
   while(totalcnt < kolbite) {
       rc=recv(sock, &buf_lin2[totalcnt], kolbite - totalcnt, 0);
       if (rc<=0) {
          printf("Сервер не прочитал\n");
          break;
       }
       totalcnt += rc;
       if (totalcnt == 4) { // прочитали размер
          memcpy(&kolbite, buf_lin2, 4); 
          kolbite += 4; // получаем размер всего блока данных
          if (kolbite > sizeof(buf_lin2)) {
             printf("Недостаточный размер буфера\n");
             break;
          }
       }
   }
   if (rc<=0 || kolbite > sizeof(buf_lin2) || kolbite <= 0) break;
   obrabwialonretr(buf_lin2, sock);
}


PS Код не запускал.
...
Рейтинг: 0 / 0
Сокеты в си
    #39088451
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
t111к...если я только знаю сколько байт приходит в одном пакете первые 4 байта пакета (204 байт), попробую только по одному пакету принимать и обрабатывать.....

Для тех кто на собаку говорит "корова" и ждёт молока под хвостом:

в TCP протоколе НЕТ пакетов.
Как только из своего лексикона уберёте эти термины - так сразу всё получится, гарантирую.
Вы мульён тысяча третий, кто наступает на грабельки открыто лежащие... и как мантру наступая на грабли повторяете - tcp+пакты :(
пока не обойдёте грабли - так и будут ошибки. можно ещё подпорочки лепить - тут уже ближе к людям в белых халатах тогда получается, чем программирование.

(круглый)
...
Рейтинг: 0 / 0
Сокеты в си
    #39088542
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolobok0,

забей, горбатого могила исправит
...
Рейтинг: 0 / 0
Сокеты в си
    #39088593
t111к
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да спасибо. Вроде подходит. Только я добавил после obrabwialonretr - break, чтобы вышел из цикла, далее нужно закрыть сокет и заново его открыть в цикле, если не выходить из цикла и не закрывать сокет и далее открывать и ждать следующего приёма данных, то неправильно работает приёмная часть кода.
Код: plaintext
1.
2.
3.
4.
5.
6.
.......
obrabwialonretr(buf_lin2, sock);
break;
 }
close(sock);
 }
...
Рейтинг: 0 / 0
Сокеты в си
    #39089445
чччД
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
t111к,

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

Пример сервера
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
//  Hello World server

#include <zmq.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>

int main (void)
{
    //  Socket to talk to clients
    void *context = zmq_ctx_new ();
    void *responder = zmq_socket (context, ZMQ_REP);
    int rc = zmq_bind (responder, "tcp://*:5555");
    assert (rc == 0);

    while (1) {
        char buffer [10];
        zmq_recv (responder, buffer, 10, 0);
        printf ("Received Hello\n");
        sleep (1);          //  Do some 'work'
        zmq_send (responder, "World", 5, 0);
    }
    return 0;
}





Пример клиента
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
//  Hello World client
#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

int main (void)
{
    printf ("Connecting to hello world server…\n");
    void *context = zmq_ctx_new ();
    void *requester = zmq_socket (context, ZMQ_REQ);
    zmq_connect (requester, "tcp://localhost:5555");

    int request_nbr;
    for (request_nbr = 0; request_nbr != 10; request_nbr++) {
        char buffer [10];
        printf ("Sending Hello %d…\n", request_nbr);
        zmq_send (requester, "Hello", 5, 0);
        zmq_recv (requester, buffer, 10, 0);
        printf ("Received World %d\n", request_nbr);
    }
    zmq_close (requester);
    zmq_ctx_destroy (context);
    return 0;
}



Библиотека ZeroMQ - понятная, надежная и быстрая. Кроме того, что она ориентирована на сообщения, в ней масса вкусностей (типа встроенной очереди сообщений и автоматического реконнекта при обрыве соединения).
И, хотя написана на С и для С, я, дельфятник использую её с удовольствием.
...
Рейтинг: 0 / 0
Сокеты в си
    #39089449
ДохтаР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Когда то пользовался но быстро не на гуглил
в функции getsocopt ( в Linux & SCO , про винду не скажу, не знаю)
есть параметр , который возвращает
количество байт находящихся
находящиеся в SO_RCVBUF
буфере, готовые для чтения приложением на момент вызова.
...
Рейтинг: 0 / 0
Сокеты в си
    #39089490
t111к
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Спасибо. Да пока стандартного сокетного приёма хватит, пока без дополнительных библиотек (ZeroMQ) обойдусь, но буду иметь ввиду , к тому же я пишу только серверную часть, данные передаются по формату протокола WialonRetranslator.
...
Рейтинг: 0 / 0
Сокеты в си
    #39089638
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
t111кДа если передающая сторона будет отсылать EOF можно было бы его ловить, но наверно передающая сторона и не посылает его


Нет, конечно же не посылает.
Ты вообще в курсе, что такое EOF ?
Он тут вообще ни при чём.
...
Рейтинг: 0 / 0
Сокеты в си
    #39089643
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kolobok0t111к...если я только знаю сколько байт приходит в одном пакете первые 4 байта пакета (204 байт), попробую только по одному пакету принимать и обрабатывать.....

Для тех кто на собаку говорит "корова" и ждёт молока под хвостом:

в TCP протоколе НЕТ пакетов.
Как только из своего лексикона уберёте эти термины - так сразу всё получится, гарантирую.
Вы мульён тысяча третий, кто наступает на грабельки открыто лежащие... и как мантру наступая на грабли повторяете - tcp+пакты :(
пока не обойдёте грабли - так и будут ошибки. можно ещё подпорочки лепить - тут уже ближе к людям в белых халатах тогда получается, чем программирование.

(круглый)


kolobok0, ты всё очень правильно написал, но только грабелек-то вообще-то и нет никаких.
Я имею в виду, что это не недостаток спецификации протокола TCP, там как раз всё чётко обозначено.
Это виртуальные грабли, которые себе придумывают программисты, не умеющие читать документацию,
но по лбу их бьют они реально.
...
Рейтинг: 0 / 0
Сокеты в си
    #39089652
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДохтаРКогда то пользовался но быстро не на гуглил
в функции getsocopt ( в Linux & SCO , про винду не скажу, не знаю)
есть параметр , который возвращает
количество байт находящихся
находящиеся в SO_RCVBUF
буфере, готовые для чтения приложением на момент вызова.

И как это относится к предмету разговора ?
((подсказка -- никак))
...
Рейтинг: 0 / 0
Сокеты в си
    #39089660
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
t111кСпасибо. Да пока стандартного сокетного приёма хватит, пока без дополнительных библиотек (ZeroMQ) обойдусь, но буду иметь ввиду , к тому же я пишу только серверную часть, данные передаются по формату протокола WialonRetranslator.

Тогда вообще не понятно, в чём там у тебя проблемы.

WialonRetranslatorОписание протокола WialonRetranslator 1.0
Входящие данные
.
Все данные приходят в бинарном формате по TCP протоколу и представляют собой пакет следующего формата:
Размер(байт) Тип поля Описание поля
4 Целое число Размер пакета
-
...
Рейтинг: 0 / 0
Сокеты в си
    #39089731
t111к
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да начал выдумывать, что может несколько пакетов данных WialonRetranslator нужно сразу принять за раз, а нужно было сделать приём одного пакета данных WialonRetranslator так как размер только одного пакета данных его нам и известен. Ну вроде сделал этот вариант, он приведён выше с моими небольшими изменениями о которых я написал.
...
Рейтинг: 0 / 0
Сокеты в си
    #39089817
ДохтаР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
t111кДа начал выдумывать, что может несколько пакетов данных WialonRetranslator нужно сразу принять за раз, а нужно было сделать приём одного пакета данных WialonRetranslator так как размер только одного пакета данных его нам и известен. Ну вроде сделал этот вариант, он приведён выше с моими небольшими изменениями о которых я написал.


Это решается буфером размером около N средних пакетов.
и массив описатель структур содержащих
смещение в буфере и размер прочитанного из сокета.

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

приблизительно так....
...
Рейтинг: 0 / 0
Сокеты в си
    #39090144
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДохтаР,

зачем так сложно?
...
Рейтинг: 0 / 0
Сокеты в си
    #39091054
ДохтаР
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилДохтаР,

зачем так сложно?

Предложите проще.

Я предложил такой вариант потому что это универсально и масштабируемо
позволяет вынести работу с сокетами в отдельный с и h
файлы и тягать между проектами, избавить от переключения
контекста в голове программиста межу прикладной и сестемной
логикой и (или) посадить еще одного програмиста на проект , так что бы
они не толкались попами внутри одного кода.
...
Рейтинг: 0 / 0
Сокеты в си
    #39091944
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДохтаР,

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

Может быть стоит использовать опыт ранее накопленный? У юниксистов например - стандартная механизация: функция вычитывания из сокета известной длины данных, с формированием входного пользовательского буфера. (подсказка: вам никто не мешает гнать перед данными их длину, тогда тип длины данных - даёт величину вычитывания кол-ва байт на длину. например 4 байта)

(круглый)
...
Рейтинг: 0 / 0
18 сообщений из 43, страница 2 из 2
Форумы / C++ [игнор отключен] [закрыт для гостей] / Сокеты в си
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]