Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 8, средняя оценка - 5.00
AntiAlianKiller
2 / 2 / 0
Регистрация: 08.05.2013
Сообщений: 14
#1

(WinSock) Условие прихода пакета данных - C++

20.07.2013, 00:07. Просмотров 1427. Ответов 6
Метки нет (Все метки)

Допустим, я хочу написать чат на WinSock. Мне нужно, чтобы при приходе пакета специально отведенный буфер заполнялся данными, после чего выводился на экран в виде текста.
Как определить, пришел ли пакет с данными? Есть ли специальное условие? На подобии " if( если пришел пакет с сервера ) { код }

Сработает-ли такое условие?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
while(true) {
recv(//чтение
             SSock,//сокет
             recv_data,//буфер куда попадут данные
             1024,//размер буфера чтения - сколько считать
             0//делаем ее аналогичной как функция read
             );
 
        if( recv_data[0] == '[' ) { // Если первый символ в буфере данных, пришедших с сервера равен началу любого сообщения... ( [???] ??? ) 
            recv_dataString = gcnew String(recv_data); // передаем строке значение буфера
            textBox4->Text = textBox4->Text + recv_dataString + Environment::NewLine; //Выводим буфер (в виде строки) в текстбокс
            recv_data[0] = '?'; //Заменяем символ, чтобы последнее сообщение, пришедшее с сервера, не выводилось циклично
            }
}
Если я правильно понимаю, пришедший однажды пакет с данными ( recv() ) заполнит буфер единожды, и после повторной проверки ( если запихнуть этот код в цикл ( а надо? ) ) он не будет заполнять буфер последними данными что он получил ( не будет выводить последнее сообщение до бесконечности ). Верно?

Если не правильно понял механику того, как это работает, напишите.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.07.2013, 00:07
Здравствуйте! Я подобрал для вас темы с ответами на вопрос (WinSock) Условие прихода пакета данных (C++):

не могу компилировать программу и надо условие проверки данных фаила на простые числа и записать их - C++
надо условие проверки данных фаила на простые числа? #include <fstream> #include <ctime> #include <cstdlib> #include <iostream> ...

Oracle Порядок прихода данных - Java БД
Всем привет. Несколько не стандартный вопрос. Сорри, если не том разделе. В массив приходят данные в следующем порядке tmpArray = ...

Прием данных Winsock и преобразование данных Byte в String - Visual Basic .NET
VB.NET Здравствуйте! Вопрос! Есть обьект winsock для обмена сообщениями tcp\ip. http://vbbook.ru/1403703567/winsock-v-visual-basicnet/ ...

Прием данных в WinSock - Visual Basic
Здравствуйте. Такой вопрос, в Winsock2_DataArrival (в самом низу кода) приходят данные с клиента (это приложение под Андроид, на нем есть...

Winsock - сливание данных - Visual Basic
Приветствую. Думаю, я не первый, у кого возникает такая проблема, но в форумах о ней ничего не нашел. Ситуация такая. Есть...

Возможно ли при импорте в модуль пакета подняться выше пакета? - Python
Есть скрипты .py, лежащие на одном уровне(в одном каталоге) и есть пакет модулей, лежащий на том же самом уровне. Возможно ли...

6
Убежденный
Ушел с форума
Эксперт С++
15708 / 7218 / 1139
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
20.07.2013, 00:38 #2
Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
Если я правильно понимаю, пришедший однажды пакет с данными ( recv() ) заполнит буфер единожды, и после повторной проверки ( если запихнуть этот код в цикл ( а надо? ) ) он не будет заполнять буфер последними данными что он получил ( не будет выводить последнее сообщение до бесконечности ). Верно?
Верно. Только с одним "но".

TCP - это просто поток байт, в нем нет такого понятия, как пакет или сообщение.
Если на одном конце кто-то вызвал send с "привет, колян!", то на другом конце
recv вовсе не обязана прочесть эту строку за один вызов, может получиться,
например, такая последовательность: "прив", "ет, кол", "ян!". Работать с TCP
следует исключительно как с потоком байт, разбитым на фрагменты заранее
неизвестного размера - только так и никак иначе. Конец "сообщения", если таковое
имеет какой-то смысл в приложении, определяется не количеством байт, прочитанных
за один вызов recv, а по содержимому этих байт (например, по какому-нибудь
маркеру или спец. символу).

Ну и не забывайте, что recv может вернуть код ошибки (-1) или 0. Последнее означает,
что удаленный компьютер разомкнул свой конец соединения.
1
AntiAlianKiller
2 / 2 / 0
Регистрация: 08.05.2013
Сообщений: 14
20.07.2013, 01:08  [ТС] #3
То есть, в моем случае (бесконечный цикл приема данных) я скорее всего приму не "[Андрей] Привет, колян!", а "[А", "н", "др", "е" и т.д. ? Или сообщение считается до конца ( или в TCP нет такого понятия, как конец или начало сообщения? ), прежде чем будет выведено на экран? Если я понял верно, мне нужно использовать UDP ( recvfrom(), sendto() ) способ подключения для моей задачи?

Добавлено через 8 минут
Если Вам не составит труда, прочитайте внимательно код в основном посте. Если мои догадки верны, то я скорее получу в текстбоксе такую надпись (Если придет сообщение: "[Андрей] Привет, колян! [qweqwe] [123]") :

C++
1
2
3
4
[А 
[q
[1
//Я не уверен, что с такой скоростью считается именно 2 символа ( не более, не менее) - просто привел пример, чтобы было понятно, что я имею ввиду
Или, если все-же сообщение считается до конца, то:

C++
1
[Андрей] Привет, колян! [qweqwe] [123]
0
Vladimir.
158 / 158 / 10
Регистрация: 24.11.2009
Сообщений: 375
20.07.2013, 01:46 #4
Если Вам не составит труда, прочитайте внимательно код в основном посте. Если мои догадки верны, то я скорее получу в текстбоксе такую надпись (Если придет сообщение: "[Андрей] Привет, колян! [qweqwe] [123]") :
Скорее всего нет. Убежденный указал вам, что recv() вовсе не обязательно прочитает всё сообщение сразу (хотя для такого короткого сообщения скорее всего так и будет). То есть, сообщение может фрагментироваться на букве "л" (например) и вы получите "[Андрей] Привет, кол". Оставшаяся часть будет принята при следующем вызове recv() но выведена в текстбокс не будет т.к. не пройдет проверку условием.
0
Убежденный
Ушел с форума
Эксперт С++
15708 / 7218 / 1139
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
20.07.2013, 10:15 #5
Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
То есть, в моем случае (бесконечный цикл приема данных) я скорее всего приму не "[Андрей] Привет, колян!", а "[А", "н", "др", "е" и т.д. ? Или сообщение считается до конца ( или в TCP нет такого понятия, как конец или начало сообщения? )
Именно. Нет такого понятия.
TCP - это просто поток байт. recv принимает этот поток частями заранее неизвестного размера.

Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
Если я понял верно, мне нужно использовать UDP ( recvfrom(), sendto() ) способ подключения для моей задачи?
Переходить на UDP необязательно, данная задача может быть решена и на TCP, просто
нужно использовать какой-то маркер для того, чтобы обозначать конец сообщения.
И recv вычитывать данные до тех пор, пока не встретится этот маркер (или ошибка).
1
AntiAlianKiller
2 / 2 / 0
Регистрация: 08.05.2013
Сообщений: 14
20.07.2013, 12:12  [ТС] #6
Т.е. нужно использовать GetToken? "[Андрей] Привет, колян!%", и считывать вплоть до символа '%' ? Как реализовать такой код? Я не совсем понимаю.
0
Убежденный
Ушел с форума
Эксперт С++
15708 / 7218 / 1139
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
20.07.2013, 13:49 #7
Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
Как реализовать такой код? Я не совсем понимаю.
Прежде всего, нужна система определения границ сообщений, передающихся по TCP.
Сам TCP, как Вы уже поняли, таких границ не предоставляет. Поэтому нужен протокол
поверх TCP, в котором эти границы были бы определены. Например, можно каждое
сообщение предварять определенным количеством байт, в которых указывать его длину.
Тогда recv сначала будет вычитывать из сокета эти байты, а затем, получив длину,
вычитывать остаток сообщения, зная сколько именно байт должно прийти.

Другой распостраненный подход - определять конец сообщения по его содержимому.
Например, в HTTP большинство сообщений имеют заголовок, в котором указывается
длина, а затем тело указанной длины. Для Вашего случая подойдет какой-нибудь
специальный символ-разделитель, который не встречается в тексте - как на счет \0 ?
То есть: "Привет, Андрей !0Как дела ?0Где вчера пропадал ?0".

Итак, протокол сформирован, теперь нужен парсер протокола - компонент, которому
вы сможете "скармливать" данные, порезанные сетью на фрагменты, и который будет
"склеивать" из них целые сообщения. Например, отправляем в парсер "При", "вет, А",
"ндрей!0Как д", "ела", "?0" - он возвращает нам строку "Привет,
Андрей" (без нуля, разумеется), затем "Как дела ?" и т.д.

Ну а дальше все просто - читаете в цикле данные из recv и кидаете их в парсер.
Он возвращает готовые целые сообщения, которые можно отображать в окне чата.
2
20.07.2013, 13:49
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.07.2013, 13:49
Привет! Вот еще темы с ответами:

Описание пакета данных - C# WCF
Как грамотно описать структуру пакетов данных для клиент-серверного приложения? Например для чата нужны примерно такие пакеты: пакет -...

Delphi winsock отправка больших данных - Delphi
Здравствуйте дорогие форумчане!! Сразу приведу кусок кода сервера: k:=0; k:=Pos('dir',buff); if k<>0 then begin ...

Знаки ? при отправки данных в winsock - Delphi
Вообщем отправляю данные через SendText Потом принимаю их так Function TConnThread.ListenHost:DWord; label Disconnect; ...

И снова WinSock. UDP. Прием данных. - C++ Builder
До сих пор мучаюсь с изучением WinSock. Уже давно получилось послать команду серверу, но теперь не получается получить от него ответ. Буфер...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.