Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Самый простой многопоточный сервер на именованных каналах, пара вопросов / 9 сообщений из 9, страница 1 из 1
03.04.2014, 16:12
    #38604489
mr_virtus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
Здравсвуйте,

я написал простой сервер, который для каждого клиента запускает отдельный поток: Клиент посылает сообщения, сервер на них отвечает. Клиенты и сервер общаются через экземпляры именованых каналов.

Вот основной код на сервере:

Код: plaintext
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.
void MainWindow::on_Run_clicked()
{
    DWORD iNp;
    int MAX_CLIENTS = 20;
    ThreadArg* ThArgs[MAX_CLIENTS];
    HANDLE hT[MAX_CLIENTS];
    for (iNp = 0; iNp < MAX_CLIENTS; iNp++){
        hNp = CreateNamedPipe(PIPE_NAME,
                              PIPE_ACCESS_DUPLEX,
                              PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE | PIPE_WAIT,
                              PIPE_UNLIMITED_INSTANCES,
                              0,
                              0,
                              INFINITE,
                              0);
        if (hNp != INVALID_HANDLE_VALUE){
            MessageBox(0, L"Named pipe is created", L"Info", MB_OK);
        }
        if (ConnectNamedPipe(hNp, 0) == 0){
            MessageBox(0, L"ConnectNamedPipe failed with with error", L"Info", MB_OK);
            CloseHandle(hNp);
        }
        ThArgs[iNp] = new ThreadArg(hNp, iNp);
        hT[iNp] = CreateThread(0, 0, ThreadFunction, ThArgs[iNp], 0, 0);
        QObject::connect(ThArgs[iNp], SIGNAL(needWriteRequest(QString)), this, SLOT(paintRequest(QString)), Qt::BlockingQueuedConnection);

    }
    WaitForMultipleObjects(iNp, hT, TRUE, INFINITE);
    for (int i =0; i < iNp; i++){
        CloseHandle(hT[i]);
        //DisconnectNamedPipe(ThArgs[i]->hNamedPipe);
    }
}

DWORD WINAPI MainWindow::ThreadFunction(LPVOID threadArg){
    ThreadArg* p = static_cast<ThreadArg*>(threadArg);
    DWORD Read;
    DWORD Written;
    char Buf[256];
    char BufWr[256];

    if (ReadFile(p->hNamedPipe, Buf, 256, &Read, 0) <= 0){
        MessageBox(0, L"ReadFile failed with error", L"Info", MB_OK);
        CloseHandle(p->hNamedPipe);
    }
    QString qstr = QString::fromUtf8(Buf);
    emit p->needWriteRequest(qstr);

    QString ans = "answer";
    strcpy(BufWr, ans.toLocal8Bit().data());
    WriteFile(p->hNamedPipe, BufWr, sizeof(BufWr), &Written, 0);
    delete p;
    return 0;
}



Вот основной код на клиенте:

Код: plaintext
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.
void MainWindow::on_CreateConnection_clicked()
{
    if (WaitNamedPipe(PIPE_NAME, NMPWAIT_WAIT_FOREVER) == 0) {
        MessageBox(0, L"WaitNamedPipe failed with error", L"Info", MB_OK);
        return;
    }

    if ((hNp = CreateFile(PIPE_NAME,
                          GENERIC_READ | GENERIC_WRITE, 0,
                          (LPSECURITY_ATTRIBUTES) NULL, OPEN_EXISTING,
                          FILE_ATTRIBUTE_NORMAL,
                          (HANDLE) NULL)) == INVALID_HANDLE_VALUE){
        MessageBox(0, L"CreateFile failed with error", L"Info", MB_OK);
    }

    DWORD Written;
    char BufWr[256];
    QString qstr = "request";
    strcpy(BufWr, qstr.toLocal8Bit().data());
    if (WriteFile(hNp, BufWr, sizeof(BufWr), &Written, NULL) == 0)
    {
        MessageBox(0, L"WriteFile failed with error", L"Info", MB_OK);
        CloseHandle(hNp);
        return;
    }
    DWORD Read;
    char Buf[256];
    if (ReadFile(hNp, Buf, 256, &Read, 0) <= 0){
        MessageBox(0, L"ReadFile failed with error", L"Info", MB_OK);
        CloseHandle(hNp);
        return;
    }
    QString qstrAns = QString::fromUtf8(Buf);
    ui->label->setText(qstrAns);
}



Проблема в том, что обмен сервер зависает в конце. Сообщения посылаются, но сервер подвисает.
И ещё. Мне нужно, чтоб клиент посылал запросы серверу периодически, а не один раз как у меня.
Как это можно исправить?

Спасибо.
...
Рейтинг: 0 / 0
03.04.2014, 16:24
    #38604508
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
Где-то в коде делается CloseHandle а потом в этот же закрытый хендл делается WriteFile.
...
Рейтинг: 0 / 0
03.04.2014, 16:32
    #38604518
smald
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
[quot mr_virtus]

Извиняюсь, что не по делу, просто интересно на каком курсе учитесь?

А, если по делу, то что у Вас thread функция не зациклена?
...
Рейтинг: 0 / 0
03.04.2014, 16:35
    #38604522
mr_virtus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
mayton,

авторГде-то в коде делается CloseHandle а потом в этот же закрытый хендл делается WriteFile.

Код: plaintext
1.
2.
3.
4.
5.
WaitForMultipleObjects(iNp, hT, TRUE, INFINITE);
    for (int i =0; i < iNp; i++){
        CloseHandle(hT[i]);
        //DisconnectNamedPipe(ThArgs[i]->hNamedPipe);
    }



Вот здесь я комментил, но результат не дало. А в другие CloseHandle я не попадаю. Или я что-тоне понимаю?=)
...
Рейтинг: 0 / 0
03.04.2014, 16:36
    #38604528
mr_virtus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
smald,

авторИзвиняюсь, что не по делу, просто интересно на каком курсе учитесь?

Предпоследний. С какой целью интересуетесь?

авторА, если по делу, то что у Вас thread функция не зациклена?

Ну да, я тоже об этом подумал. Что по идее, если нужно несколько раз слать сообщения, то нужно писать цикл. Как в нем только задать условие выхода?
...
Рейтинг: 0 / 0
03.04.2014, 17:09
    #38604562
smald
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
mr_virtus
Ну да, я тоже об этом подумал. Что по идее, если нужно несколько раз слать сообщения, то нужно писать цикл. Как в нем только задать условие выхода?

Цикл должен быть в thread функции, а то у Вас сервак в отдельном
потоке слушает, читает, делает write, и умирает.
И цикл в клиенте. Выход хоть через регистрацию обработчика POSIX сигнала, хоть отслеживание
действий пользователя в GUI. Да море возможностей, какой-нибудь QtButton повесьте,
и назначьте слотом на сигнал о клике уничтожение процесса.
...
Рейтинг: 0 / 0
03.04.2014, 23:11
    #38604926
mr_virtus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
Код: plaintext
1.
2.
3.
Цикл должен быть в thread функции, а то у Вас сервак в отдельном
потоке слушает, читает, делает write, и умирает.
И цикл в клиенте



Ну да. В клиенте точно. Думаю, чтоб периодически отправлять запросы с клиента использовать таймер.

Еще с одной ошибкой разобрался, почему висел сервак:

авторWaitForMultipleObjects(iNp, hT, TRUE, INFINITE);
авторВыход хоть через регистрацию обработчика POSIX сигнала, хоть отслеживание
действий пользователя в GUI.

Не очень понял момент - " через регистрацию обработчика POSIX".? А отслеживать действия пользователя - это, например, при нажатии кнопки - убивается процесс?
...
Рейтинг: 0 / 0
03.04.2014, 23:36
    #38604936
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
mr_virtusВот здесь я комментил, но результат не дало. А в другие CloseHandle я не попадаю. Или я что-тоне понимаю?=)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
DWORD WINAPI MainWindow::ThreadFunction(LPVOID threadArg){
    ThreadArg* p = static_cast<ThreadArg*>(threadArg);
    DWORD Read;
    DWORD Written;
    char Buf[256];
    char BufWr[256];

    if (ReadFile(p->hNamedPipe, Buf, 256, &Read, 0) <= 0){
        MessageBox(0, L"ReadFile failed with error", L"Info", MB_OK);
        CloseHandle(p->hNamedPipe);
    }
    QString qstr = QString::fromUtf8(Buf);
    emit p->needWriteRequest(qstr);

    QString ans = "answer";
    strcpy(BufWr, ans.toLocal8Bit().data());
    WriteFile(p->hNamedPipe, BufWr, sizeof(BufWr), &Written, 0);
    delete p;
    return 0;
}
...
Рейтинг: 0 / 0
04.04.2014, 09:11
    #38605075
mr_virtus
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Самый простой многопоточный сервер на именованных каналах, пара вопросов
mayton,

Вот здесь я комментил, но результат не дало. А в другие CloseHandle я не попадаю. Или я что-тоне понимаю?=)


авторDWORD WINAPI MainWindow::ThreadFunction(LPVOID threadArg){
ThreadArg* p = static_cast<ThreadArg*>(threadArg);
DWORD Read;
DWORD Written;
char Buf[256];
char BufWr[256];

if (ReadFile(p->hNamedPipe, Buf, 256, &Read, 0) <= 0){
MessageBox(0, L"ReadFile failed with error", L"Info", MB_OK);
CloseHandle(p->hNamedPipe);
}
QString qstr = QString::fromUtf8(Buf);
emit p->needWriteRequest(qstr);

QString ans = "answer";
strcpy(BufWr, ans.toLocal8Bit().data());
WriteFile(p->hNamedPipe, BufWr, sizeof(BufWr), &Written, 0);
delete p;
return 0;
}

Я думаю дело не в этом. В этот CloseHandle мы попадаем, только если не смогли прочитать байты.

Там проблема была в функции
WaitForMultipleObjects(iNp, hT, TRUE, INFINITE);
Я поставил max_clients = 20;
а сам не запускал столько клиентов, вот сервер и вис.

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


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