С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
2 / 2 / 0
Регистрация: 08.05.2013
Сообщений: 14
1

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

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

Author24 — интернет-сервис помощи студентам
Допустим, я хочу написать чат на 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.07.2013, 00:07
Ответы с готовыми решениями:

Порядок прихода данных
Всем привет. Несколько не стандартный вопрос. Сорри, если не том разделе. В массив приходят данные...

Вывод даты прихода товаров из данных регистра бухгалтерии.
Добрый день! Подскажите пожалуйста, как-то можно вывести дату прихода(расхода) по каждой...

Прием данных Winsock и преобразование данных Byte в String
VB.NET Здравствуйте! Вопрос! Есть обьект winsock для обмена сообщениями tcp\ip....

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

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

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

Ну и не забывайте, что recv может вернуть код ошибки (-1) или 0. Последнее означает,
что удаленный компьютер разомкнул свой конец соединения.
2
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
377 / 228 / 79
Регистрация: 24.11.2009
Сообщений: 695
20.07.2013, 01:46 4
Если Вам не составит труда, прочитайте внимательно код в основном посте. Если мои догадки верны, то я скорее получу в текстбоксе такую надпись (Если придет сообщение: "[Андрей] Привет, колян! [qweqwe] [123]") :
Скорее всего нет. Убежденный указал вам, что recv() вовсе не обязательно прочитает всё сообщение сразу (хотя для такого короткого сообщения скорее всего так и будет). То есть, сообщение может фрагментироваться на букве "л" (например) и вы получите "[Андрей] Привет, кол". Оставшаяся часть будет принята при следующем вызове recv() но выведена в текстбокс не будет т.к. не пройдет проверку условием.
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
20.07.2013, 10:15 5
Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
То есть, в моем случае (бесконечный цикл приема данных) я скорее всего приму не "[Андрей] Привет, колян!", а "[А", "н", "др", "е" и т.д. ? Или сообщение считается до конца ( или в TCP нет такого понятия, как конец или начало сообщения? )
Именно. Нет такого понятия.
TCP - это просто поток байт. recv принимает этот поток частями заранее неизвестного размера.

Цитата Сообщение от AntiAlianKiller Посмотреть сообщение
Если я понял верно, мне нужно использовать UDP ( recvfrom(), sendto() ) способ подключения для моей задачи?
Переходить на UDP необязательно, данная задача может быть решена и на TCP, просто
нужно использовать какой-то маркер для того, чтобы обозначать конец сообщения.
И recv вычитывать данные до тех пор, пока не встретится этот маркер (или ошибка).
1
2 / 2 / 0
Регистрация: 08.05.2013
Сообщений: 14
20.07.2013, 12:12  [ТС] 6
Т.е. нужно использовать GetToken? "[Андрей] Привет, колян!%", и считывать вплоть до символа '%' ? Как реализовать такой код? Я не совсем понимаю.
0
Ушел с форума
Эксперт С++
16478 / 7441 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 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
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.07.2013, 13:49
Помогаю со студенческими работами здесь

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

И снова WinSock. UDP. Прием данных.
До сих пор мучаюсь с изучением WinSock. Уже давно получилось послать команду серверу, но теперь не...

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

Знаки ? при отправки данных в winsock
Вообщем отправляю данные через SendText Потом принимаю их так Function...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru