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

Клиент-сервер на СИ++. Запись клиентом строки и её чтение с сервера

21.05.2019, 12:27. Показов 2738. Ответов 7

Студворк — интернет-сервис помощи студентам
Добрый день/вечер/утро(нужное подчеркнуть). Столкнулся с такой проблемой: у меня есть клиент, который записывает информацию, и сервер, который её считывает. Клиент записывает строку.
Понятное дело, что сервер просто должен её считать.
Но у меня не выходит считывание.

Клиент и сервер я создавал в разных проектах. Так что, надо будет сваять два проекта, и в первую очередь запустить сервер.

Код КЛИЕНТА

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
#include "stdafx.h"
#include <windows.h>
#include <iostream>
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hslot;
 
    TCHAR slotname[35] = TEXT("\\\\.\\mailslot\\demoslot"); // Имя клиента
    hslot = CreateFile(slotname, GENERIC_WRITE, // Тип доступа - запись 
        FILE_SHARE_READ, // Разрешает последующие операции открытия объекта, которые требуют доступа для чтения.
        NULL, 
        OPEN_EXISTING, // Открывает файл. Функция завершается ошибкой, если файл не существует.
        0, // Атрибуты файла(архивирован, только для чтения, скрытый). У нас файл обычный 
        NULL);
    // Клиент выступает как файл
 
    if (hslot == INVALID_HANDLE_VALUE)
    {
        std::cout << "SLOT WRITING FAILED" << std::endl;
        std::cout << "PRESS KEY TO FINISH" << std::endl;
        std::cin.get();
        return 0;
    }
 
    std::cout << "SLOT IS WAITING" << std::endl;
    TCHAR just_write[20] = TEXT("Hello, server"); // Наше сообщение
    DWORD dwBytesWrite;
    if (!WriteFile(hslot, just_write, sizeof(just_write), &dwBytesWrite, NULL))
    {
        // Выводим в случае провала отправки сообщения
        std::cout << "WRITE FAILED" << std::endl;
        CloseHandle(hslot);
        std::cout << "PRESS KEY TO FINICH" << std::endl;
        std::cin.get();
        return 0;
    }
    // В случае успеха выводим то, что отправили
    std::wcout << "Data WRITTEN TO BOX: " << just_write << std::endl;
    std::cout << "PRESS KEY TO FINISH" << std::endl;
    CloseHandle(hslot);
    std::cin.get();
 
    return 0;
    return 0;
}
Код СЕРВЕРА

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
#include "stdafx.h"
#include <windows.h>
#include <iostream>
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE hslot;
    TCHAR slotname[35] = TEXT("\\\\.\\mailslot\\demoslot"); // Имя сервера
    hslot = CreateMailslot(slotname, 0, MAILSLOT_WAIT_FOREVER, NULL); // Создаём сервер
 
    // Аргументы функции CreateMailslot
    //1) slotname - Имя сервера
    //2) 0 - максимальный размер получаемого сообщения(если стоит ноль, то сообщение может быть любого размера)
    //3) MAILSLOT_WAIT_FOREVER - определяет количество времени ожидания сообщения. В нашем случае ждём ВЕЧНО
    //4) NULL - указываем, может ли наследоваться(у нас нет)
 
    if (hslot == INVALID_HANDLE_VALUE) // Если не получилось создать сервер
    {
        std::cout << "SLOT FAILED" << std::endl;
        std::cout << "PRESS KEY TO FINISH" << std::endl;
        std::cin.get();
        return 0; // Завершаем программу
    }
 
    std::cout << "SERVER SLOT IS WAITING" << std::endl; // Выводим сообщение о том, что сервер ждёт от нас ответа
    TCHAR message[] = TEXT("");
    DWORD dwBytesRead; // Сколько байтов прочитали
    // Производим чтение из файла
    if (!ReadFile(hslot, message, sizeof(message), &dwBytesRead, (LPOVERLAPPED)NULL))
    {
        std::cout << "READING SLOT FAILED" << std::endl;
        CloseHandle(hslot);
        std::cout << "PRESS KEY TO FINISH" << std::endl;
        std::cin.get();
        return 0;
    }
    std::wcout << "Data Read: " << message << std::endl;
    std::cout << "PRESS KEY TO FINISH" << std::endl;
    CloseHandle(hslot);
    std::cin.get();
 
    return 0;
    return 0;
}
Ещё хотел уточнить, что если TCHAR message[] = TEXT("")(что описано в коде сервера - 27 строка) изменить на TCHAR message[20], тогда всё заработает, но мы же заранее не знаем, какой размер будет у нашего сообщения. Так что, хотелось бы избежать такого "костыля".

Заранее благодарю за помощь
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.05.2019, 12:27
Ответы с готовыми решениями:

Чтение данных с сервера (TCP клиент)
Добрый день подскажите как реализовать чтение данных с сервера непрерывным потоком и выводить все в TextView. отправку на сервер...

Клиент/сервер зависание сервера
Приветствую всех. Недавно начал изучать C# .NET да и вообще C#. На данный момент пишу что-то типо ICQ. Сделал регистрацию и вход, но...

Асинхронный клиент-сервер. Рассылка от сервера
Здравствуйте! Пишу клиент - серверное приложения на асинхронных сокетах. Задача состоит в том, чтобы при получении сервером...

7
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
21.05.2019, 13:18
Лучший ответ Сообщение было отмечено DOJ745 как решение

Решение

Цитата Сообщение от DOJ745 Посмотреть сообщение
Ещё хотел уточнить, что если TCHAR message[] = TEXT("")(что описано в коде сервера - 27 строка) изменить на TCHAR message[20],
TCHAR message[] = TEXT("") - Это буфер размером 1
TCHAR message[20] - Это буфер размером 20


Цитата Сообщение от DOJ745 Посмотреть сообщение
тогда всё заработает, но мы же заранее не знаем, какой размер будет у нашего сообщения. Так что, хотелось бы избежать такого "костыля".
сделай TCHAR message[1024]; , хотя бы.
И, лучше здесь TCHAR не использовать, используй char
1
Эксперт CЭксперт С++
 Аватар для liv
5120 / 4574 / 855
Регистрация: 07.10.2015
Сообщений: 9,462
21.05.2019, 13:25
DOJ745, сваял "на коленке" примерчик, чтобы только показать идею:
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include    <windows.h>
#include    <iostream>
 
using namespace std;
 
HANDLE  hWatchThreadMailClient, hWatchThreadMailServer;
DWORD   dwThreadIDMailClient, dwThreadIDMailServer;
 
BOOL FAR PASCAL MailSlotServer(LPSTR lpData)
{
    HANDLE      hMailSlot;
    DWORD       cbMessage, cMessage, cbRead;
    BOOL        fResult;
    char        *pdata = NULL;
    LPCSTR      lpszSlotName = "\\\\.\\mailslot\\TestMailSlot";
 
    hMailSlot = CreateMailslotA(lpszSlotName,
        0,                                      // no maximum message size        
        MAILSLOT_WAIT_FOREVER,          // no time-out for read operations 
        (LPSECURITY_ATTRIBUTES)NULL);   // no security attributes 
 
    if (hMailSlot == INVALID_HANDLE_VALUE)
        return FALSE;
    else
    {
        // бесконечный цикл
        while (TRUE)
        {
            cMessage = cbMessage = cbRead = 0;
 
            fResult = GetMailslotInfo(hMailSlot,
                (LPDWORD)NULL,                      // no maximum message size
                &cbMessage,                             // size of next message
                &cMessage,                              // number of messages
                (LPDWORD)NULL);                     // no read time-out
 
            if (!fResult)
                break;                                  // выходим геть !
 
            if (cbMessage == MAILSLOT_NO_MESSAGE)// а нету ничего
                continue;
 
            pdata = new char[cbMessage];
 
            fResult = ReadFile(hMailSlot, pdata, cbMessage, &cbRead, (LPOVERLAPPED)NULL);
 
            if (!fResult)
            {
                delete[]pdata;
                break;                                  // выходим геть !
            }
 
            cout << "Server: " << pdata << endl;
            delete[]pdata;
        }
    }
    return FALSE;
} // end of MailSlotServer()
 
BOOL FAR PASCAL MailSlotClient(LPSTR lpData)
{
    BOOL        fResult;
    HANDLE      hFile;
    DWORD       cbWritten;
    const char  *pTest = "Test of MailSlot";
 
    hFile = CreateFileA("\\\\*\\mailslot\\TestMailSlot",
        GENERIC_WRITE,
        FILE_SHARE_READ,            // required to write to a mailslot
        (LPSECURITY_ATTRIBUTES)NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        (HANDLE)NULL);
 
    if (hFile == INVALID_HANDLE_VALUE)
        return FALSE;
    else
    {
        // бесконечный цикл
        while(TRUE)
        {
            cout << "Client: " << pTest << endl;
            fResult = WriteFile(hFile,
                pTest,
                strlen(pTest)+1,
                &cbWritten,
                (LPOVERLAPPED)NULL);
 
            if (!fResult)
            {
                CloseHandle(hFile);
                break;
            }
            Sleep(1000);
        }
    }
    return FALSE;
} // end of MailSlotClient()
 
int main()
{
    hWatchThreadMailClient = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
        (LPTHREAD_START_ROUTINE)MailSlotClient, 0, 0, &dwThreadIDMailClient);
 
    hWatchThreadMailServer = CreateThread((LPSECURITY_ATTRIBUTES)NULL, 0,
        (LPTHREAD_START_ROUTINE)MailSlotServer, 0, 0, &dwThreadIDMailServer);
 
    while (TRUE);
    return 0;
}
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
21.05.2019, 13:29
DOJ745, Сделай динамический буфер
Если ReadFile вернула FALSE, проверяй ::GetLastError - если ERROR_INSUFFICIENT_BUFFER, то бефер слишком маленький, надо увеличить до dwBytesRead
0
Эксперт CЭксперт С++
 Аватар для liv
5120 / 4574 / 855
Регистрация: 07.10.2015
Сообщений: 9,462
21.05.2019, 13:33
Чтобы узнать длину принятого сообщения есть функция GetMailslotInfo()

Добавлено через 3 минуты
oleg-m1973, любим костыли?
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
21.05.2019, 13:40
Цитата Сообщение от liv Посмотреть сообщение
Чтобы узнать длину принятого сообщения есть функция GetMailslotInfo()
Добавлено через 3 минуты
oleg-m1973, любим костыли?
Где ты нашёл костыли?
Если вызов ReadFile блокирующий, то да, лучше использовать GetMailslotInfo (только не надо каждый раз выделать новый буфер).
Если неблокирующий - то эффективнее без лишнего вызова - скорее всего ReadFile начитает всё в уже выделенный буфер, и только если тот слишком маленький выделается новый и делается второй вызов ReadFile
0
Эксперт CЭксперт С++
 Аватар для liv
5120 / 4574 / 855
Регистрация: 07.10.2015
Сообщений: 9,462
21.05.2019, 13:47
oleg-m1973, ладно, уговорил, можно по-разному. Все пути ведут в Рим!
0
0 / 0 / 0
Регистрация: 24.02.2019
Сообщений: 18
22.05.2019, 23:47  [ТС]
Всем спасибо. Решил проблему банальным увеличением объёма считываемых данных
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
22.05.2019, 23:47
Помогаю со студенческими работами здесь

Чтение массива байтов (сервер-клиент)
Всем привет. Столкнулся вот с такой задачей. В общем есть клиент-серверное приложение. Сервер отсылает данные клиенту через сокет, также...

Сервер/клиент. Чтение результата *.exe
У меня имеются и серверское приложение, и клиентское. Подскажите, как делать в дальнейшем, в Java-серверском после обработки ...

Технология клиент-сервер. Классы клиента и сервера. Обсуждение
В данном теме выкладываю свои классы клиента и сервера, а так же простеньких примеров реализованных на этих классах. Жду конструктивной...

Запись/чтение в клиент-сервере
есть приложение которое с сервера отправляет файлы клиентам, на данный момент может отправлять только текстовые файлы до 64кб размером, а...

Принятие сообщений от сервера в бесконечном цикле (Клиент-Сервер Чат)
Если кто то написал сообщение то это сообщение обрабатывает сервер и рассылает всех клиентам.. Но проблема в том что не понимаю как...


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

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru