S>то сервер получает только 3-й сенд?
я не очень понял, а откуда вывод про то, что сервер так реагирует?
и вообще что значит для сервера первый или второй? если это TCP, то сервер сколько захочет (сможет) столько и отдаст
Здравствуйте, Александр, Вы писали:
А>я не очень понял, а откуда вывод про то, что сервер так реагирует? А>и вообще что значит для сервера первый или второй? если это 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'а. Где собака зарыта?
Здравствуйте, IGor_79, Вы писали:
IG_>Слишком мало информации, но как первый вариант, IG_>который приходит в голову — вы вызывается recv IG_>в цикле и первые два буфера перезаписываются
Здравствуйте, Satrapp, Вы писали:
S>что-то я не понимаю кое-чего... Почему, если я с клиента посылаю 2 раза S>то сервер получает только 3-й сенд?
Помоему вы немного недопонимаете логику работы Winsock и протокола TCP. При работе с TCP, вовсе не нужно на каждый send вызывать recv, и соответсвенно, это совсем не означает, что вызывав три раза send и потом вызвав 3 раза recv вы получите соответсвующие send'ам данные. К примеру, вы посылаете 10 раз по 2 байта, на другой стороне вы вызываете recv и получаете за один раз все данные..
Протокол TCP — stream-"ориентированный" протокол. Есть ещё такое понятие, как алгоритм Нагла. Действуя по этому алоритму, драйвер протокола TCP может поождать когда накопится определённое кол-во данных и послать их одной посылкой. И наконец, есть такое понятие "блокирующие" сокеты. Вызывая recv с большим буфером, он блокирует вашу программу и не отдаст вам управление, пока не заполнит буфер полностью. Хотя под виндами это обходится
довольно легко..
Выводы:
расскажите более подробно что вам нужно и как вы это хотите сделать
Пытаться манипулировать настройками сокетов
Использовать неблокирующую архитектуру
Использовать UDP
.. ещё что-нибудь, в зависимости от потребностей и от возможностей.
довольно легко.. B>Выводы: B> расскажите более подробно что вам нужно и как вы это хотите сделать
мне необходимо отослать 2 порции данных. Использую блокирующие стрим-сокеты. Проблема еще в том, что между этими двумя сендами — три строчки кода... И настроить селект таким образом, чтобы он успел встрять между ними — занятие сомнительное... Неужели единственный выход в данном случае — сливать оба сенда в один и на приеме их уже разбирать? Размер отправляемых данных заранее не известен. Точно известно лишь то, что они не будут превышать 4-5 кб
... << Rsdn@Home 1.1.4 beta 1 >> В winamp'е зажигает Damned For All Time;Blood Money
довольно легко.. B>>Выводы: B>> расскажите более подробно что вам нужно и как вы это хотите сделать S>мне необходимо отослать 2 порции данных. Использую блокирующие стрим-сокеты. Проблема еще в том, что между этими двумя сендами — три строчки кода... И настроить селект таким образом, чтобы он успел встрять между ними — занятие сомнительное... Неужели единственный выход в данном случае — сливать оба сенда в один и на приеме их уже разбирать? Размер отправляемых данных заранее не известен. Точно известно лишь то, что они не будут превышать 4-5 кб
если ты работаеш с TCP сокетами, то тебе нужно передавать размер данных или какой-нить признак конца "порции", и на принимающей стороне разбивать на части
Здравствуйте, Александр, Вы писали:
А>если ты работаеш с TCP сокетами, то тебе нужно передавать размер данных
простите мою темноту в этом вопросе, только начал изучать сокеты
как можно передать размер данных, если не тем же send'ом? А> или какой-нить признак конца "порции", и на принимающей стороне разбивать на части
но ведь прежде чем разбить, надо как-то их получить?
вот я и говорю, что неужели единственный вариант — отсылать "все и сразу", одним сендом?
... << Rsdn@Home 1.1.4 beta 1 >> В winamp'е зажигает 13-Tell Me Why
Здравствуйте, butcher, Вы писали:
B>Здравствуйте, Satrapp, Вы писали:
B>Протокол TCP — stream-"ориентированный" протокол. Есть ещё такое понятие, как алгоритм Нагла. Действуя по этому алоритму, драйвер протокола TCP может поождать когда накопится определённое кол-во данных и послать их одной посылкой. И наконец, есть такое понятие "блокирующие" сокеты. Вызывая recv с большим буфером, он блокирует вашу программу и не отдаст вам управление, пока не заполнит буфер полностью.
Программа блокируется до наличия байтов в приемном буфере гнезда, а не до заполнения пользовательского буфера. В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины.
Здравствуйте, Satrapp, Вы писали:
S>но ведь прежде чем разбить, надо как-то их получить? S>вот я и говорю, что неужели единственный вариант — отсылать "все и сразу", одним сендом?
Посмотрите: Алгоритм Нагла Обращение к задающим вопросы по сокетам
Здравствуйте, butcher, Вы писали:
B>Здравствуйте, Satrapp, Вы писали:
S>>но ведь прежде чем разбить, надо как-то их получить? S>>вот я и говорю, что неужели единственный вариант — отсылать "все и сразу", одним сендом? B>Посмотрите: B>Алгоритм Нагла
а причет тут алгоритм Найгла то? человек же говорил, что посылает килобайты! а сей алгоритм ограничивается несколькими байтами! B>Обращение к задающим вопросы по сокетам
Здравствуйте, 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. это что все данные будут доставленны и придут в том же порядке, в котором ты их и отправлял
Здравствуйте, Александр, Вы писали:
А>а причет тут алгоритм Найгла то? человек же говорил, что посылает килобайты! а сей алгоритм ограничивается несколькими байтами!
он сказал что размер данных не будет превышать 4..5 килобайт. Несколько байт тоже не превышают, а ссылку я дал чтобы он почитал, ума разума набрался..
Здравствуйте, Алексей Мартынов, Вы писали:
АМ>Здравствуйте, butcher, Вы писали:
B>>Здравствуйте, Satrapp, Вы писали:
B>>Протокол TCP — stream-"ориентированный" протокол. Есть ещё такое понятие, как алгоритм Нагла. Действуя по этому алоритму, драйвер протокола TCP может поождать когда накопится определённое кол-во данных и послать их одной посылкой. И наконец, есть такое понятие "блокирующие" сокеты. Вызывая recv с большим буфером, он блокирует вашу программу и не отдаст вам управление, пока не заполнит буфер полностью.
АМ>Программа блокируется до наличия байтов в приемном буфере гнезда, а не до заполнения пользовательского буфера. В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины.
Чуть-чуть добавлю . Также recv в блокирующем режиме вернет управление в случае:
-закрытия соединения удаленным хостом (При этом функция вернет 0 (нет ошибки) и кол-во прочитанных байт == 0). Приложение должно корректно обработать этот случай и более не вызывать recv на этом сокете — иначе возможно зависание потока в логически бесконечном цикле (попытка прочесть данные, когда соединение закрыто. IE например так делает в некоторых случаях)
-или при возникновении ошибки (скорее всего: сброса соединения удаленным хостом)
Здравствуйте, Алексей Мартынов, Вы писали:
АМ>Программа блокируется до наличия байтов в приемном буфере гнезда, а не до заполнения пользовательского буфера.
А какой смысл тогда возвращать управление, если
режим блокирующий
данные ещё не в пользовательском буфере
Напомню ещё про пример
, который работает в винде, а в unix'е уходит в блокировку.
АМ>В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины.
Это ещё почему?
Здравствуйте, butcher, Вы писали:
B>Здравствуйте, Александр, Вы писали:
А>>а причет тут алгоритм Найгла то? человек же говорил, что посылает килобайты! а сей алгоритм ограничивается несколькими байтами! B>он сказал что размер данных не будет превышать 4..5 килобайт. Несколько байт тоже не превышают, а ссылку я дал чтобы он почитал, ума разума набрался..
нельзя такие вещи говорить начинающем! потом все кидаются отключать этот "вредный" алгоритм
АМ>>В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины. B>Это ещё почему?
странный вопрос... а откуда ты знаеш длинны HTTP сообщения? или почтового SMTP, POP3? все они посылают данные переменной длины, с опредененным признаком конца данных скажем два CRLF
Здравствуйте, Александр, Вы писали:
АМ>>>В противном случае невозможно написать дешевое получение неизвестного объема данных, а чтение, например, HTTP-запроса и HTTP-ответа и есть чтение блока данных неизвестной длины. B>>Это ещё почему? А>странный вопрос... а откуда ты знаеш длинны HTTP сообщения? или почтового SMTP, POP3? все они посылают данные переменной длины, с опредененным признаком конца данных скажем два CRLF
Способов написания такого кода много. Я недопонял утверждение "Программа блокируется до наличия байтов в приемном буфере гнезда" ..
Сейчас дошло, ну в принципе да, когда данных нет, нет смысла больше держать программу. Я это и хотел сказать, просто обобщил в контексте его задачи, то что он за один recv принимает больше данных из-за того что указал большой буфер...