2 send подряд
От: Satrapp Россия  
Дата: 06.09.04 14:54
Оценка:
что-то я не понимаю кое-чего... Почему, если я с клиента посылаю 2 раза
strcpy(Msg, "qwerty1");
send(sock, Msg, nSize, 0);
...
strcpy(Msg, "qwerty2");
send(sock, Msg, nSize, 0);

а на сервере принимаю
recv(m_Socket, Users, 256, 0);

то сервер реагирует только на второй send? Соответственно, если 3 раза сендить
strcpy(Msg, "qwerty1");
send(sock, Msg, nSize, 0);
...
strcpy(Msg, "qwerty2");
send(sock, Msg, nSize, 0);
...
strcpy(Msg, "qwerty3");
send(sock, Msg, nSize, 0);

то сервер получает только 3-й сенд?
... << Rsdn@Home 1.1.4 beta 1 >> В winamp'е зажигает A Kind Of Magic
Re: 2 send подряд
От: Александр Россия  
Дата: 06.09.04 15:31
Оценка:
Здравствуйте, Satrapp, Вы писали:

S>что-то я не понимаю кое-чего... Почему, если я с клиента посылаю 2 раза

S>
S>strcpy(Msg, "qwerty1");
S>send(sock, Msg, nSize, 0);
S>...
S>strcpy(Msg, "qwerty2");
S>send(sock, Msg, nSize, 0);
S>

S>а на сервере принимаю
S>
S>recv(m_Socket, Users, 256, 0);
S>

S>то сервер реагирует только на второй send? Соответственно, если 3 раза сендить
S>
S>strcpy(Msg, "qwerty1");
S>send(sock, Msg, nSize, 0);
S>...
S>strcpy(Msg, "qwerty2");
S>send(sock, Msg, nSize, 0);
S>...
S>strcpy(Msg, "qwerty3");
S>send(sock, Msg, nSize, 0);
S>

S>то сервер получает только 3-й сенд?
я не очень понял, а откуда вывод про то, что сервер так реагирует?
и вообще что значит для сервера первый или второй? если это TCP, то сервер сколько захочет (сможет) столько и отдаст
... << RSDN@Home 1.1.4 @@subversion >>
Re: 2 send подряд
От: IGor_79 Украина  
Дата: 06.09.04 15:59
Оценка:
Здравствуйте, Satrapp, Вы писали:

S> [skipped]


Слишком мало информации, но как первый вариант,
который приходит в голову — вы вызывается recv
в цикле и первые два буфера перезаписываются
Re[2]: 2 send подряд
От: Satrapp Россия  
Дата: 07.09.04 06:41
Оценка:
Здравствуйте, Александр, Вы писали:

А>я не очень понял, а откуда вывод про то, что сервер так реагирует?

А>и вообще что значит для сервера первый или второй? если это TCP, то сервер сколько захочет (сможет) столько и отдаст

на самом деле код примерно такой (сервер):
bytes_read = recv(sock, Message, 1024, 0); // (2) прием данных
if(bytes_read <= 0) break;

char MsgToSend[4096];
sprintf(MsgToSend, "%s", some_string1);

int ns = send(sock, MsgToSend, nSize, MSG_DONTROUTE); // (3) первый раз отправляем ответ...
if(SOCKET_ERROR == ns) break; // тут пропускает. ns>0

sprintf(MsgToSend, "%s", some_string2);
nSize = strlen(MsgToSend) + 1;
        
send(sock, MsgToSend, nSize, 0); // (5) второй раз уходит ответ.


код клиента:
char Message[1024];
int  nSize;

strcpy(Message, some_string);
nSize = strlen(Message)+1;
if (SOCKET_ERROR == send(m_Socket, Message, nSize, 0)) { // (1) проходит нормально
    return 1;
}

bytes_read = recv(m_Socket, buf, 4096, 0); // (4) первый ответ сервера
if(bytes_read <= 0) return 1;

// ... работа с buf

bytes_read = recv(m_Socket, OfflMsgs, 4096, 0); // (6) второй ответ сервера
if(bytes_read <= 0) return 1;

а все работает не так, как хотелось бы... А хотелось бы так: клиент сначала посылает некие данные (1) и ждет ответа (4). Сервер их принимает (2). Формирует первую порцию данных и отсылает ответ клиенту (3). Клиент их принимает (4). Затем формирует вторую порцию данных и отправляет их на тот же сокет (5). Клиент принимает вторую порцию ответа (6). А на самом деле происходит следующее: клиент нормально отсылает, сервер нормально принимает, формирует первую порцию ответа, делает вид, что отправляет (send возвращает нормальное значение > 0). Но на самом деле клиент все еще висит на (4). Затем сервер формирует вторую порцию ответа и отсылает их на тот же сокет. Только после этого клиент сдвигается с (4) и получает данные. Но почему-то не первые, а уже вторые. Если после второго send'а поставить еще один send, то сервер забъет и на второй send. Клиент отреагирует только после третьего send'а. Где собака зарыта?
... << Rsdn@Home 1.1.4 beta 1 >> В winamp'е зажигает It's Hardlife
Re[2]: 2 send подряд
От: Satrapp Россия  
Дата: 07.09.04 06:43
Оценка:
Здравствуйте, IGor_79, Вы писали:

IG_>Слишком мало информации, но как первый вариант,

IG_>который приходит в голову — вы вызывается recv
IG_>в цикле и первые два буфера перезаписываются

Re[2]: 2 send подряд
Автор: Satrapp
Дата: 07.09.04
... << Rsdn@Home 1.1.4 beta 1 >> В winamp'е зажигает 06-Volga Boatman
Re: 2 send подряд
От: butcher Россия http://bu7cher.blogspot.com
Дата: 07.09.04 09:58
Оценка: 1 (1)
Здравствуйте, Satrapp, Вы писали:

S>что-то я не понимаю кое-чего... Почему, если я с клиента посылаю 2 раза

S>то сервер получает только 3-й сенд?
Помоему вы немного недопонимаете логику работы Winsock и протокола TCP. При работе с TCP, вовсе не нужно на каждый send вызывать recv, и соответсвенно, это совсем не означает, что вызывав три раза send и потом вызвав 3 раза recv вы получите соответсвующие send'ам данные. К примеру, вы посылаете 10 раз по 2 байта, на другой стороне вы вызываете recv и получаете за один раз все данные..
Протокол TCP — stream-"ориентированный" протокол. Есть ещё такое понятие, как алгоритм Нагла. Действуя по этому алоритму, драйвер протокола TCP может поождать когда накопится определённое кол-во данных и послать их одной посылкой. И наконец, есть такое понятие "блокирующие" сокеты. Вызывая recv с большим буфером, он блокирует вашу программу и не отдаст вам управление, пока не заполнит буфер полностью. Хотя под виндами это обходится
Автор: butcher
Дата: 14.05.04
довольно легко..
Выводы:
  • расскажите более подробно что вам нужно и как вы это хотите сделать
  • Пытаться манипулировать настройками сокетов
  • Использовать неблокирующую архитектуру
  • Использовать UDP
  • .. ещё что-нибудь, в зависимости от потребностей и от возможностей.

  • Нет ничего невозможного..
    Re[3]: 2 send подряд
    От: Александр Россия  
    Дата: 07.09.04 10:19
    Оценка:
    Здравствуйте, Satrapp, Вы писали:

    [Поскипано]
    осталось выяснить самую малость где и как выделяются и удаляются буфера под receive в твоем примере этого не видно, и какой тип сокета
    ... << RSDN@Home 1.1.4 @@subversion >>
    Re[2]: 2 send подряд
    От: Satrapp Россия  
    Дата: 07.09.04 11:26
    Оценка:
    Здравствуйте, butcher, Вы писали:

    B>...под виндами это обходится
    Автор: butcher
    Дата: 14.05.04
    довольно легко..

    B>Выводы:
    B>
  • расскажите более подробно что вам нужно и как вы это хотите сделать
    мне необходимо отослать 2 порции данных. Использую блокирующие стрим-сокеты. Проблема еще в том, что между этими двумя сендами — три строчки кода... И настроить селект таким образом, чтобы он успел встрять между ними — занятие сомнительное... Неужели единственный выход в данном случае — сливать оба сенда в один и на приеме их уже разбирать? Размер отправляемых данных заранее не известен. Точно известно лишь то, что они не будут превышать 4-5 кб
    ... << Rsdn@Home 1.1.4 beta 1 >> В winamp'е зажигает Damned For All Time;Blood Money
  • Re[3]: 2 send подряд
    От: Александр Россия  
    Дата: 07.09.04 12:48
    Оценка:
    Здравствуйте, Satrapp, Вы писали:

    S>Здравствуйте, butcher, Вы писали:


    B>>...под виндами это обходится
    Автор: butcher
    Дата: 14.05.04
    довольно легко..

    B>>Выводы:
    B>>
  • расскажите более подробно что вам нужно и как вы это хотите сделать
    S>мне необходимо отослать 2 порции данных. Использую блокирующие стрим-сокеты. Проблема еще в том, что между этими двумя сендами — три строчки кода... И настроить селект таким образом, чтобы он успел встрять между ними — занятие сомнительное... Неужели единственный выход в данном случае — сливать оба сенда в один и на приеме их уже разбирать? Размер отправляемых данных заранее не известен. Точно известно лишь то, что они не будут превышать 4-5 кб
    если ты работаеш с TCP сокетами, то тебе нужно передавать размер данных или какой-нить признак конца "порции", и на принимающей стороне разбивать на части
    ... << RSDN@Home 1.1.4 @@subversion >>
  • Re[4]: 2 send подряд
    От: Satrapp Россия  
    Дата: 07.09.04 12:58
    Оценка:
    Здравствуйте, Александр, Вы писали:

    А>если ты работаеш с TCP сокетами, то тебе нужно передавать размер данных

    простите мою темноту в этом вопросе, только начал изучать сокеты
    как можно передать размер данных, если не тем же send'ом?
    А> или какой-нить признак конца "порции", и на принимающей стороне разбивать на части
    но ведь прежде чем разбить, надо как-то их получить?
    вот я и говорю, что неужели единственный вариант — отсылать "все и сразу", одним сендом?
    ... << Rsdn@Home 1.1.4 beta 1 >> В winamp'е зажигает 13-Tell Me Why
    Re[2]: 2 send подряд
    От: Алексей Мартынов Россия  
    Дата: 07.09.04 13:09
    Оценка: 5 (1) +1
    Здравствуйте, butcher, Вы писали:

    B>Здравствуйте, Satrapp, Вы писали:


    B>Протокол TCP — stream-"ориентированный" протокол. Есть ещё такое понятие, как алгоритм Нагла. Действуя по этому алоритму, драйвер протокола TCP может поождать когда накопится определённое кол-во данных и послать их одной посылкой. И наконец, есть такое понятие "блокирующие" сокеты. Вызывая recv с большим буфером, он блокирует вашу программу и не отдаст вам управление, пока не заполнит буфер полностью.


    Программа блокируется до наличия байтов в приемном буфере гнезда, а не до заполнения пользовательского буфера. В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины.

    Alexey Martynov
    Алексей Мартынов
    Re[5]: 2 send подряд
    От: butcher Россия http://bu7cher.blogspot.com
    Дата: 07.09.04 13:16
    Оценка:
    Здравствуйте, Satrapp, Вы писали:

    S>но ведь прежде чем разбить, надо как-то их получить?

    S>вот я и говорю, что неужели единственный вариант — отсылать "все и сразу", одним сендом?
    Посмотрите:
    Алгоритм Нагла
    Обращение к задающим вопросы по сокетам
    Автор: Maxim S. Shatskih
    Дата: 12.06.04

    Нет ничего невозможного..
    Re[6]: 2 send подряд
    От: Александр Россия  
    Дата: 07.09.04 14:36
    Оценка:
    Здравствуйте, butcher, Вы писали:

    B>Здравствуйте, Satrapp, Вы писали:


    S>>но ведь прежде чем разбить, надо как-то их получить?

    S>>вот я и говорю, что неужели единственный вариант — отсылать "все и сразу", одним сендом?
    B>Посмотрите:
    B>Алгоритм Нагла
    а причет тут алгоритм Найгла то? человек же говорил, что посылает килобайты! а сей алгоритм ограничивается несколькими байтами!
    B>Обращение к задающим вопросы по сокетам
    Автор: Maxim S. Shatskih
    Дата: 12.06.04
    ... << RSDN@Home 1.1.4 @@subversion >>
    Re[5]: 2 send подряд
    От: Александр Россия  
    Дата: 07.09.04 14:36
    Оценка: +1
    Здравствуйте, Satrapp, Вы писали:

    S>Здравствуйте, Александр, Вы писали:


    А>>если ты работаеш с TCP сокетами, то тебе нужно передавать размер данных

    S>простите мою темноту в этом вопросе, только начал изучать сокеты
    S>как можно передать размер данных, если не тем же send'ом?
    ну например надо тебе послать данные (скажем строку "Test") ты формируеш буфер отправки типа такого: buf = (int)SIZE("Test") + "Test", и оправляеш, а на принимающей стороне читает первые sizeof(int) байт и получаеш размер пакета.

    A> или какой-нить признак конца "порции", и на принимающей стороне разбивать на части

    S>но ведь прежде чем разбить, надо как-то их получить?
    S>вот я и говорю, что неужели единственный вариант — отсылать "все и сразу", одним сендом?
    так ты получаеш все! неважно сколько было сендов и сколько было ресивов... в итеге ты получиш ровно столько, сколько отослал, но не факт, что ровно такими же порциями т.е.
    посылаем два пакета
    1) 12345
    2) 67890

    получить можем:
    1) все сразу 1234567890
    2) так же как и посылали 12345 67890
    3) кусками 123 4567 890
    ну и куча вариаций на пункт 3
    единственное что гарантирует TCP. это что все данные будут доставленны и придут в том же порядке, в котором ты их и отправлял
    ... << RSDN@Home 1.1.4 @@subversion >>
    Re[7]: 2 send подряд
    От: butcher Россия http://bu7cher.blogspot.com
    Дата: 07.09.04 15:23
    Оценка:
    Здравствуйте, Александр, Вы писали:

    А>а причет тут алгоритм Найгла то? человек же говорил, что посылает килобайты! а сей алгоритм ограничивается несколькими байтами!

    он сказал что размер данных не будет превышать 4..5 килобайт. Несколько байт тоже не превышают, а ссылку я дал чтобы он почитал, ума разума набрался..

    Нет ничего невозможного..
    Re[3]: 2 send подряд
    От: TarasCo  
    Дата: 07.09.04 15:45
    Оценка: 5 (1)
    Здравствуйте, Алексей Мартынов, Вы писали:

    АМ>Здравствуйте, butcher, Вы писали:


    B>>Здравствуйте, Satrapp, Вы писали:


    B>>Протокол TCP — stream-"ориентированный" протокол. Есть ещё такое понятие, как алгоритм Нагла. Действуя по этому алоритму, драйвер протокола TCP может поождать когда накопится определённое кол-во данных и послать их одной посылкой. И наконец, есть такое понятие "блокирующие" сокеты. Вызывая recv с большим буфером, он блокирует вашу программу и не отдаст вам управление, пока не заполнит буфер полностью.


    АМ>Программа блокируется до наличия байтов в приемном буфере гнезда, а не до заполнения пользовательского буфера. В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины.


    Чуть-чуть добавлю . Также recv в блокирующем режиме вернет управление в случае:
    -закрытия соединения удаленным хостом (При этом функция вернет 0 (нет ошибки) и кол-во прочитанных байт == 0). Приложение должно корректно обработать этот случай и более не вызывать recv на этом сокете — иначе возможно зависание потока в логически бесконечном цикле (попытка прочесть данные, когда соединение закрыто. IE например так делает в некоторых случаях)
    -или при возникновении ошибки (скорее всего: сброса соединения удаленным хостом)
    Да пребудет с тобою сила
    Re[3]: 2 send подряд
    От: butcher Россия http://bu7cher.blogspot.com
    Дата: 07.09.04 16:54
    Оценка: 10 (1)
    Здравствуйте, Алексей Мартынов, Вы писали:

    АМ>Программа блокируется до наличия байтов в приемном буфере гнезда, а не до заполнения пользовательского буфера.

    А какой смысл тогда возвращать управление, если
  • режим блокирующий
  • данные ещё не в пользовательском буфере
    Напомню ещё про пример
    Автор: butcher
    Дата: 14.05.04
    , который работает в винде, а в unix'е уходит в блокировку.

    АМ>В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины.

    Это ещё почему?

  • Нет ничего невозможного..
    Re[8]: 2 send подряд
    От: Александр Россия  
    Дата: 08.09.04 06:20
    Оценка: :)
    Здравствуйте, butcher, Вы писали:

    B>Здравствуйте, Александр, Вы писали:


    А>>а причет тут алгоритм Найгла то? человек же говорил, что посылает килобайты! а сей алгоритм ограничивается несколькими байтами!

    B>он сказал что размер данных не будет превышать 4..5 килобайт. Несколько байт тоже не превышают, а ссылку я дал чтобы он почитал, ума разума набрался..
    нельзя такие вещи говорить начинающем! потом все кидаются отключать этот "вредный" алгоритм
    ... << RSDN@Home 1.1.4 @@subversion >>
    Re[4]: 2 send подряд
    От: Александр Россия  
    Дата: 08.09.04 06:20
    Оценка: 10 (1)
    Здравствуйте, butcher, Вы писали:


    АМ>>В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины.

    B>Это ещё почему?

    странный вопрос... а откуда ты знаеш длинны HTTP сообщения? или почтового SMTP, POP3? все они посылают данные переменной длины, с опредененным признаком конца данных скажем два CRLF
    ... << RSDN@Home 1.1.4 @@subversion >>
    Re[5]: 2 send подряд
    От: butcher Россия http://bu7cher.blogspot.com
    Дата: 08.09.04 06:33
    Оценка:
    Здравствуйте, Александр, Вы писали:

    АМ>>>В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины.

    B>>Это ещё почему?
    А>странный вопрос... а откуда ты знаеш длинны HTTP сообщения? или почтового SMTP, POP3? все они посылают данные переменной длины, с опредененным признаком конца данных скажем два CRLF
    Способов написания такого кода много. Я недопонял утверждение "Программа блокируется до наличия байтов в приемном буфере гнезда" ..
    Сейчас дошло, ну в принципе да, когда данных нет, нет смысла больше держать программу. Я это и хотел сказать, просто обобщил в контексте его задачи, то что он за один recv принимает больше данных из-за того что указал большой буфер...

    Нет ничего невозможного..
    Подождите ...
    Wait...
    Пока на собственное сообщение не было ответов, его можно удалить.