Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / send и recv / 14 сообщений из 14, страница 1 из 1
07.07.2005, 16:53
    #33155303
TnedutS
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
Привет всем!

У меня есть клиент и сервер.
В обоих по 2 потока.

На клиенте потоки разделены грубо говоря на передающий и принимающий.
На сервере немного не так.
1 поток.
//Принимаем запрос
while((bytes_recv = recv(client_socket,&buff[0],sizeof(buff),0)) > 0)
{
...

case 2:
{

buff[0] = LOGICALREPLY;
//Исполняем функцию
buff[1] =registerSinkAddress(&buff[1]);

semTake(semSend,WAIT_FOREVER);
//логический результат выполнения сразу шлем клиенту
send(client_socket,&buff[0],2,0);
semGive(semSend);

printf("regAddress\n");
break;
}
...
}

И есть у сервера второй поток. Он время от времени шлет некоторые сообщения тому же клиенту.

semTake(semSend,WAIT_FOREVER);
int sendA= send(client_socket,&sendBuff[0],sendLength,0);
printf(" %d\n",sendA);
semGive(semSend);

Проблема в том, что на клиентской стороне сообщения воспринимаются как одно.
То есть как одна дейтаграмма.

while((recvSize=recv(my_sock,&recvBuff[0],
sizeof(recvBuff)-1,0))>0 && isConnect==true)
{
// display
printf("S=>C:%d \n",recvSize);

recvSize получается как сумма длин 2 сообщений - 2 + sendLength!
Поставил даже семафоры - ничего не изменилось.
Почему так?
Ведь вроде как send посылает целую дейтаграмму, а recv целыми же дейтаграммами и читает. Почему объединяются 2 сообщения?

По идее я могу и на сервере разделить потоки четко на передающий и принимающий.
Наверное, это все решит.
Но не хотелось бы...
И кроме того просто интересно, почему так.
...
Рейтинг: 0 / 0
07.07.2005, 18:13
    #33155536
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
А потому что у тебя ОДИН канал связи между клиентом и сервером. Потоков там может быть сколько угодно, но до тех пор пока подключение одно общее - все пакеты в нем будут идти в одном общем потоке.
В общем, самое простое решение этой задачи - клиент делает два подключения к серверу на разные порты или даже на один и тот же, но тогда в первой посылке после подключения клиент устанавливает для канала его статус - канал для запросов от клиента и канал для сообщений клиенту.
...
Рейтинг: 0 / 0
07.07.2005, 20:29
    #33155698
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
Попробуйте поиграться длиной буфера и флагами-статусом. Это наведёт Вас на решение...

Из спецификации на TCP (не дословно)...
"...TCP не регламентирует немедленную доставку буфера приёма до процесса приёма... Команда PUSH активирует проталкивание данных до процесса приёма на стороне клиента, даже если буффер данных не до конца наполнен..."

где то так...смысл надеюсь передал...

с уважением
(круглый)
...
Рейтинг: 0 / 0
11.07.2005, 11:58
    #33159048
TnedutS
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
Не мог сразу ответить - уезжал.

Сейчас попробую оба варианта.
Начну с флагов лучше:)

И еще сомнения по поводу 2 потоков. Еще не проверенные, но...
Допустим, я сделаю 2 канала. Ну так все равно оба потока сервера буду отправлять данные в один поток данных, который предназначен для передачи Server->Client. И тогда будет то же самое. Или все же нет?
...
Рейтинг: 0 / 0
11.07.2005, 12:34
    #33159175
roman10
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
Я не уверен, но по моему, нельзя работать с одним и тем сокетом из разных потоков (без синхронизации).
...
Рейтинг: 0 / 0
11.07.2005, 12:49
    #33159188
TnedutS
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
roman10Я не уверен, но по моему, нельзя работать с одним и тем сокетом из разных потоков (без синхронизации).

Без какой синхронизации? Можно поподробнее?
...
Рейтинг: 0 / 0
11.07.2005, 17:40
    #33159965
White Owl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
TnedutSНачну с флагов лучше:)
Какие флаги???

TnedutSИ еще сомнения по поводу 2 потоков. Еще не проверенные, но...
Допустим, я сделаю 2 канала. Ну так все равно оба потока сервера буду отправлять данные в один поток данных, который предназначен для передачи Server->Client. И тогда будет то же самое. Или все же нет?
Повторяю: Каналов должно быть два! Один для запросов клиента к серверу. Второй для посылок сообщений от сервера к клиенту. Это самое простое решение.

Можно сделать все и на одном канале. Но тогда надо делать на сервере/клиенте один процесс принимает/передает данные. Каждый логический пакет данных предваряется описанием какого этот пакет типа и длиной пакета. И процесс непосредственно работающий с сокетом уже отправляет по IPC каналам полученый пакет в нужный процесс. То есть реализовать принцип очереди.
...
Рейтинг: 0 / 0
11.07.2005, 17:57
    #33160021
TnedutS
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
White Owl TnedutSНачну с флагов лучше:)
Какие флаги???

TnedutSИ еще сомнения по поводу 2 потоков. Еще не проверенные, но...
Допустим, я сделаю 2 канала. Ну так все равно оба потока сервера буду отправлять данные в один поток данных, который предназначен для передачи Server->Client. И тогда будет то же самое. Или все же нет?
Повторяю: Каналов должно быть два! Один для запросов клиента к серверу. Второй для посылок сообщений от сервера к клиенту. Это самое простое решение.

Можно сделать все и на одном канале. Но тогда надо делать на сервере/клиенте один процесс принимает/передает данные. Каждый логический пакет данных предваряется описанием какого этот пакет типа и длиной пакета. И процесс непосредственно работающий с сокетом уже отправляет по IPC каналам полученый пакет в нужный процесс. То есть реализовать принцип очереди.

Все. Наконец-то дошло:)
Спасибо.
Первый способ мне гораздо больше нравится.
Попробую.
...
Рейтинг: 0 / 0
11.07.2005, 18:54
    #33160116
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
а теперь правильный вопрос...
точнее совет дня...
рекомендую сделать следующее...
1) на приёме сделать ожидание пакета, но длину буфера влепите ноль. Запрос вернёт (поприходу пакета) длину пакета реальную. следующей строкой сделайте выборку функцией ресиив, с указанной длиной. это классика. мать её.



удачи вам
(круглый)
ЗЫ
Предпологаю, что данные просто буфферизируються в Вашем буфере. Либо подгоните длину буфера под один пакет. Длину сделайте одинаковую во всех типах пакетов.
ЗЫ ЗЫ
ик...
...
Рейтинг: 0 / 0
11.07.2005, 19:03
    #33160129
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
кстати по поводу каналов....

1) TCP протокол обеспечивает соединение поинт-поинт (точка-точка) и гарантирует целостную и упорядочную доставку данных как в одну так и в другую сторону.
2) В нутри протокола существует логика передачи инфы в две стороны.
3) Соединение идентифицируеться такими параметрами как IP адресс (IP уровень) и TCP порт (TCP уровень).
4) Порт предназначен для идентификации различных процессов работающих на данном хосте или маршрутиризаторе.

короче говоря, что это я поехал пересказывать протокол то ?
старею...

гляньте тут лучше...

http://www.helloworld.ru/show.php?curraz=50

с уважением
(круглый)
ЗЫ
Кстати спецификации на протокол описывают и протокол с процессами юзающих данный протокол. Гляньте - очень интересные нюансы мона узнать. Под виндами - думаю докопаться до ориджинал так же мона :)
...
Рейтинг: 0 / 0
12.07.2005, 12:35
    #33161081
TnedutS
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
kolobok01) на приёме сделать ожидание пакета, но длину буфера влепите ноль. Запрос вернёт (поприходу пакета) длину пакета реальную. следующей строкой сделайте выборку функцией ресиив, с указанной длиной. это классика. мать её.


Объясните, пожалуйста, что за ожидание пакета?
Если функцией recv, то здесь:
while((recvSize=recv(my_sock,&recvBuff[0],
/*sizeof(recvBuff)-1*/0,0))>0 && isConnect==true)
{
int recvSize2 = recv(my_sock,&recvBuff[0],recvSize,0);
...
}

recvSize будет равен 0.
И recvSize, соответственно, тоже.
...
Рейтинг: 0 / 0
12.07.2005, 12:36
    #33161083
TnedutS
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
TnedutS kolobok01) на приёме сделать ожидание пакета, но длину буфера влепите ноль. Запрос вернёт (поприходу пакета) длину пакета реальную. следующей строкой сделайте выборку функцией ресиив, с указанной длиной. это классика. мать её.


Объясните, пожалуйста, что за ожидание пакета?
Если функцией recv, то здесь:
while((recvSize=recv(my_sock,&recvBuff[0],
/*sizeof(recvBuff)-1*/0,0))>0 && isConnect==true)
{
int recvSize2 = recv(my_sock,&recvBuff[0],recvSize,0);
...
}

recvSize будет равен 0.
И recvSize, соответственно, тоже.

И recvSize2, соответственно, тоже:)
...
Рейтинг: 0 / 0
12.07.2005, 16:14
    #33161776
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
1) По поводу принятия инфы...Если провести следующий тест...
а) на передающей стороне посылаем 2 байта и в след 3 байта.
б) на приёмной стороне примем (если долго спали) 5 байт.
TCP обеспечивает Вам поток, ни о каких пакетах речь и не идёт :) .

2) По поводу принятия длины. Знаете визуально помню - где то код валялся. Не могу найти. Да, в том контексте который юзаете Вы - абсолютно верно. Вернёться нул. Но млин, я когда то так же использовал сОкеты. Потом попалось другое решение - именно в разграничении фаз приёма и наполнении буфера. Хотя если Вы опять проспите - то в следующий раз примете два подряд куска данных. Что не снимает проблему.

3) Выход - либо стандартной длины данные. Либо парсить поток (код-длина).


с уважением
(круглый)
...
Рейтинг: 0 / 0
12.07.2005, 17:27
    #33162019
TnedutS
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
send и recv
kolobok01) По поводу принятия инфы...Если провести следующий тест...
а) на передающей стороне посылаем 2 байта и в след 3 байта.
б) на приёмной стороне примем (если долго спали) 5 байт.
TCP обеспечивает Вам поток, ни о каких пакетах речь и не идёт :) .


По идее долго спать клиент не должен. Ну буду иметь ввиду. Спасибо.

kolobok0
2) По поводу принятия длины. Знаете визуально помню - где то код валялся. Не могу найти. Да, в том контексте который юзаете Вы - абсолютно верно. Вернёться нул. Но млин, я когда то так же использовал сОкеты. Потом попалось другое решение - именно в разграничении фаз приёма и наполнении буфера. Хотя если Вы опять проспите - то в следующий раз примете два подряд куска данных. Что не снимает проблему.

3) Выход - либо стандартной длины данные. Либо парсить поток (код-длина).


с уважением
(круглый)

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


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