Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/15: Рейтинг темы: голосов - 15, средняя оценка - 4.60
4 / 4 / 0
Регистрация: 06.11.2013
Сообщений: 18

TCP Client

08.07.2019, 15:11. Показов 2898. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте.

Делаю приложение, в котором есть 3 события
1-ButtonInitClick-Инициализация
2-ButtonSendClick-отсылка сообщения
3-ButtonReadClick-чтение сообщения

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#include <Winsock2.h>
//#include <SysUtils.hpp>
  WSADATA wsaData;
  SOCKET ConnectSocket;  // впускающий сокет и сокет для клиентов
  sockaddr_in ServerAddr;  // это будет адрес сервера
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonInitClick(TObject *Sender)
{
wsaData.
    int err, maxlen = 512;  // код ошибки и размер буферов
    char* recvbuf=new char[maxlen];  // буфер приема
 
    // Initialize Winsock
    WSAStartup(MAKEWORD(2,2), &wsaData);
 
    // Connect to server
    ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 
    ServerAddr.sin_family=AF_INET;
 
    ServerAddr.sin_addr.s_addr=inet_addr("127.0.0.1");
    ServerAddr.sin_port=htons(50001);
 
    err = connect( ConnectSocket, (sockaddr *) &ServerAddr, sizeof(ServerAddr));
 
    if (err == SOCKET_ERROR) {
        //printf("connect failed: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return;
    }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonSendClick(TObject *Sender)
{
char Text[100];
StrPCopy(Text,EditSend->Text);
send( ConnectSocket,  Text,EditSend->Text.Length() , 0 );
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ButtonReadClick(TObject *Sender)
{
char query[100];
int len=100;
recv(ConnectSocket, query, len, 0);//Виснет здесь!!!
MemoResult->Text=query;
}
//---------------------------------------------------------------------------
Проблема в событии чтения из сокета, а именно если сервер отослал данные до момента наступления ButtonReadClick, то все отрабатывается нормально.
Если сервер ни чего не отослал то происходит зависание на моменте чтения из буфера до момента пока сервер не отошлет хотя бы 1 байт.
Как решить мою проблему?

Краткое описание приложения:
Приложение считывает данные с прибора у которого скорострельность маленькая и низкий приоритет насвязь и есть большая вероятность пропуска пакета. По этой причине в ответ на запрос может ни чего не прийти.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.07.2019, 15:11
Ответы с готовыми решениями:

TCP/IP пакеты. Как можно изменить служебные параметры заголовка TCP или UDP?
Всем привет! Работаю с передачей данных через интернет. Как можно изменить служебные параметры заголовка TCP или UDP (флаги, контрольная...

как создать TCP клиент, TCP сервер ? На С++
Очень нужна помощь!Как написать TCP клиент, TCP сервер. Например,клиент вводит строку с клавиатуры и отсылает ее серверу.только перед...

C++ rtmp client
Здравствуйте! Возникла необходимость создать клиент работающий по протоколу rtmp. Принцип работы: вызов методов клиентом на стороне...

10
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
08.07.2019, 17:46
Цитата Сообщение от XRinat Посмотреть сообщение
Если сервер ни чего не отослал то происходит зависание на моменте чтения из буфера до момента пока сервер не отошлет хотя бы 1 байт.
Как решить мою проблему?
Проверить, что данные пришли, при помощи, например, ::ioctlsocket(.... FIONREAD ....), либо select, потом вызывать recv
1
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
09.07.2019, 06:22
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
::ioctlsocket(.... FIONREAD ....)
так лучше не делать. в сетевом программировании это считается плохой практикой(хотя бы потому, что пакеты могут быть нулевого размера).
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
либо select, потом вызывать recv
это правильно, но select для блокирующего сокета может сыграть злую шутку: https://stackoverflow.com/ques... 34#5352634
поэтому рекомендуется использовать неблокирующий сокет. но тут возникнет проблема с тем, что функция send может отправить меньше байтов, чем вы хотите и надо следить за этим.
но это на выбор ТСа.
1
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
09.07.2019, 08:50
Цитата Сообщение от GbaLog- Посмотреть сообщение
так лучше не делать. в сетевом программировании это считается плохой практикой(хотя бы потому, что пакеты могут быть нулевого размера).
Не считается. FIONREAD вернёт ноль в двух случаях - когда нет данных и при разрыве коннекта. То же самое сделает неблокирующий recv.
Однако, в отличие от неблокирующих сокетов, можно по-нажатию кнопки проверить при помощи ioctlsocket, что данные есть, а потом подождать пока придёт весь пакет, при помощи блокирующего recv
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
09.07.2019, 09:12
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Не считается.
да ну? покажите мне хотя бы несколько репозиториев, где оно используется именно в том сценарии, в котором вы предлагаете.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
FIONREAD вернёт ноль в двух случаях - когда нет данных и при разрыве коннекта.
ага, а для UDP:
man udp 7
FIONREAD (SIOCINQ)
Gets a pointer to an integer as argument. Returns the size of
the next pending datagram in the integer in bytes, or 0 when no
datagram is pending. Warning: Using FIONREAD, it is impossible
to distinguish the case where no datagram is pending from the
case where the next pending datagram contains zero bytes of
data.
It is safer to use select(2), poll(2), or epoll(7) to
distinguish these cases.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Однако, в отличие от неблокирующих сокетов, можно по-нажатию кнопки проверить при помощи ioctlsocket
и чем тогда ioctl отличается от неблокирующего recv?
кроме того, что через recv мы сразу и получим статус и прочитаем сообщение, если оно есть.
P.S. если вы сейчас попытаетесь мне сказать, что неблокирующий recv не гарантирует того, что всё сообщение будет прочитано, то вспомните для начала, что tcp может вообще разбивать пакеты на однобайтовые и вы в любом случае по нажатию кнопки получите какой-нибудь огрызок данных.
P.P.S. а вообще, я агитирую не за неблокирующие сокеты, а за select. про неблокирующие сокеты я сказал лишь потому, что у select'a там имеется как минимум одна проблема с блокирующими.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
09.07.2019, 09:21
Цитата Сообщение от GbaLog- Посмотреть сообщение
ага, а для UDP:
Речь вроде идёт об TCP, не надо мешать в одну кучу

Добавлено через 1 минуту
Цитата Сообщение от GbaLog- Посмотреть сообщение
и чем тогда ioctl отличается от неблокирующего recv?
кроме того, что через recv мы сразу и получим статус и прочитаем сообщение, если оно есть.
Тем, что ioctl не получает данные. Через неблокирующий recv мы получим кусок данных, потом придётся нажимать кнопку снова, чтоб получить остаток.

Добавлено через 59 секунд
Цитата Сообщение от GbaLog- Посмотреть сообщение
да ну? покажите мне хотя бы несколько репозиториев, где оно используется именно в том сценарии, в котором вы предлагаете.
Ну да. Тебя только репозитории убеждают?

Добавлено через 1 минуту
Цитата Сообщение от GbaLog- Посмотреть сообщение
P.P.S. а вообще, я агитирую не за неблокирующие сокеты, а за select. про неблокирующие сокеты я сказал лишь потому, что у select'a там имеется как минимум одна проблема с блокирующими.
Да select/poll это конечно хорошо и правильно, но здесь они не нужны. Здесь роль этого селекта, пусть и урезанную, исполняет кнопка

Добавлено через 59 секунд
Цитата Сообщение от GbaLog- Посмотреть сообщение
P.S. если вы сейчас попытаетесь мне сказать, что неблокирующий recv не гарантирует того, что всё сообщение будет прочитано, то вспомните для начала, что tcp может вообще разбивать пакеты на однобайтовые и вы в любом случае по нажатию кнопки получите какой-нибудь огрызок данных.
В случае блокирующего получим столько, сколько запросили
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
09.07.2019, 09:42
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Речь вроде идёт об TCP, не надо мешать в одну кучу
а вы в своём приложении разграничиваете TCP и UDP на уровне сокетов?
стандартная архитектура примерно такая:
на самом низком уровне есть пул сокетов(SOCKET в винде и int в Unix), которые запихиваются в fdset, pollfd, kevent, etc.
потом вызывается select, poll/WSAPoll, epoll, kevent, etc.
если что-то заматчилось, то мы передаём об этом информацию в более высокоуровневую структуру, где до сих пор нет никаких разграничений на tcp/udp.
там выделяется место(если ещё не выделено) для пришедшего сообщения. вот на этом моменте мы можем использовать ioctl с FIONREAD.
потом все данные читаются и запихиваются в буфер.
потом сигнал о том, что что-то было прочитано, передаётся юзеру этого глобального цикла.

что вы предлагаете противопоставить такому подходу? разграничивать tcp и udp, чтобы 2 раза вызывать select, poll, etc?
как думаете, как на вас сообщество посмотрит?
это всё к слову о том, что у вас там что-то принято использовать, а у реального сообщества - нет.
никто не использует FIONREAD до того, как стало ясно, что что-то уже пришло.

Добавлено через 12 минут
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Ну да. Тебя только репозитории убеждают?
а что меня ещё должно убеждать? слова рандомного человека с форума? извольте.
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Здесь роль этого селекта, пусть и урезанную, исполняет кнопка
нет. select нужен для того, чтобы проверить, что происходит с сокетом.
кнопку нажимает человек, который понятия не имеет, что там с сокетом.
собственно, весь топик о том, чтобы при нажатии этой кнопки проверялось для начала, что что-то принято.

Цитата Сообщение от oleg-m1973 Посмотреть сообщение
В случае блокирующего получим столько, сколько запросили
сами-то проверяли?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
09.07.2019, 09:42
Цитата Сообщение от GbaLog- Посмотреть сообщение
а вы в своём приложении разграничиваете TCP и UDP на уровне сокетов?
Конечно. Логика обработки данных абсолютно разная. Для tcp вполне можно сначала запросить количество данных в буфере, потом сделать блокирующий recv. Да, некрасиво, но нет ничего криминального.

Цитата Сообщение от GbaLog- Посмотреть сообщение
это всё к слову о том, что у вас там что-то принято использовать, а у реального сообщества - нет.
никто не использует FIONREAD до того, как стало ясно, что что-то уже пришло.
Это слишком сильное утверждение. Как насчёт какого-то "реального сообщества", так и насчёт "никто".
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
09.07.2019, 09:53
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Это слишком сильное утверждение. Как насчёт какого-то "реального сообщества", так и насчёт "никто".
ну я привёл, естественно, одну из стратегий.
существует ещё множество.
и некоторые из них даже распространены. взять хоть Apache web-server, там всё блокирующее, т.к. на одно соединение порождается один процесс.
и я, может, немного погорячился, сказав, что никто не использует.
кто-нибудь обязательно использует.
вы, например.

Добавлено через 4 минуты
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Конечно. Логика обработки данных абсолютно разная.
и в чём же разница на уровне сокетов?
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Для tcp вполне можно сначала запросить количество данных в буфере, потом сделать блокирующий recv. Да, некрасиво, но нет ничего криминального.
для UDP тоже. я даже больше скажу, так и делают, только после select, poll, epoll, etc. когда стало известно, что уже что-то пришло.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
09.07.2019, 09:54
Цитата Сообщение от GbaLog- Посмотреть сообщение
и некоторые из них даже распространены. взять хоть Apache web-server, там всё блокирующее, т.к. на одно соединение порождается один процесс.
и я, может, немного погорячился, сказав, что никто не использует.
Да, я пользуюсь только только блокирующими сокетами, хотя бы затем, чтоб не заморачиваться с connect.
Перед тем, как делать recv, я делаю FIONREAD, чтоб выделить буфер нужного размера (конечно, после select/poll, но, в данном случае, это не важно)
0
153 / 148 / 66
Регистрация: 20.02.2014
Сообщений: 556
10.07.2019, 03:41
oleg-m1973, GbaLog-, господа, вы обсуждаете урезанный функционал bsd интерфейса сокетов под винду, который был реализован лишь для более простого портирования туловин из nix мира. Микрософт специально давно уже придумала отличный интерфейс winsock2, с функциями WSA, где наиболее точно можно подобрать необходимую функцию для вызова. Все остальные рассуждения, как лучше использовать bsd socket под Windows - не более, чем попытки скрестить ежа с ужом.
XRinat, а по существу - после нажатия кнопки использовать select() с таймаутом, непример в 1 секунду, и если по таймауту ошибка - то ничего не получено.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.07.2019, 03:41
Помогаю со студенческими работами здесь

FTP client
Здравствуйте. У меня задание - написать простенький ftp-клиент, не используя стандартных классов типа CInternetConnection, а используя...

SMTP GMAIL Client
Долго разбирался с тем как нужно все правильно с smtp на Си, в итоге получился такой, вроде как рабочий клиент #define...

Torrent client
Вот и всё! как можно организовать???

Соединение tcp client и tcp server
accept(); bind(); connect(); listen(); socket(); Нужно расположить их в порядке в каком их вызывает (А) сервер (Б) клиент, чтобы...

TCP-client and TCP-Server
Добрый день. Нужен сервер. В моем случае это пример-примитив. Проблема. Если я в IP клиента указываю 192.168.1.3(Мой ПК), то сервер с...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru