Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Сервер-клиент.отправка сообщений


Автор: weirdo 21.10.2007, 14:38
Даны два процесса-клиент и сервер...среда разработки VS 6.0 .
Должны передаваться сообщения как от клиетну серверу так и обратно...тут ошибка...не могу найти...помогите плиз.То есть серверу,например, сообщение пишу..и оно уходит в никуда...до клиента не доходит и наоборот...а должно отображаться.

Сервер:

#include <conio.h>
#include <stdio.h>
#include <windows.h>


#define BUFFER_SIZE 1024 //1k

void quit(HANDLE hNamedPipe) {

    CloseHandle(hNamedPipe);
    printf("\nProcess zavershen...");

}

int main() {

    HANDLE    hNamedPipe;                                // Идентификатор канала Pipe
    LPSTR    lpszPipeName = "\\\\.\\pipe\\$MyPipe$";    // Имя создаваемого канала Pipe
    BOOL    fConnected;                                // Флаг успешного создания канала
    DWORD    cbRead;                                    // Количество байт данных, принятых через канал
    DWORD    cbWritten;                                // Количество байт данных, переданных через канал


    // Создаем канал Pipe, имеющий имя lpszPipeName
    hNamedPipe = CreateNamedPipe(
        lpszPipeName,
        PIPE_ACCESS_DUPLEX,
        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
        PIPE_UNLIMITED_INSTANCES,
        512,
        512,
        5000,
        NULL);
    
    // Проверка создания канала
    if(hNamedPipe == INVALID_HANDLE_VALUE) {
        printf("CreateNamedPipe: Oshibka ");
        printf("%ld\n", GetLastError());
        quit(hNamedPipe);
        getch();
        return 0;
    }

    // Ожидаем соединения со стороны клиента
    fConnected = ConnectNamedPipe(hNamedPipe, NULL);

    // При возникновении ошибки выводим ее код
    if(!fConnected) {
        switch(GetLastError()) {
        case ERROR_NO_DATA:
            printf("ConnectNamedPipe: ERROR_NO_DATA");
            quit(hNamedPipe);
            getch();
            return 0;
        case ERROR_PIPE_CONNECTED:
            printf("ConnectNamedPipe: ERROR_PIPE_CONNECTED");
            quit(hNamedPipe);
            getch();
            return 0;
        case ERROR_PIPE_LISTENING:
            printf("ConnectNamedPipe: ERROR_PIPE_LISTENING");
            quit(hNamedPipe);
            getch();
            return 0;
        case ERROR_CALL_NOT_IMPLEMENTED:
            printf("ConnectNamedPipe: ERROR_CALL_NOT_IMPLEMENTED");
            quit(hNamedPipe);
            getch();
            return 0;
        default:
            printf("ConnectNamedPipe: Ошибка ");
            printf("%ld\n", GetLastError());
            quit(hNamedPipe);
            getch();
            return 0;
        }
        quit(hNamedPipe);
        getch();
        return 0;
    }

    // Выводим сообщение об успешном создании канала
    printf("Connected...\n");

    char WMess[BUFFER_SIZE];                    // написанное сообщение
    char RMess[BUFFER_SIZE];                    // полученное сообщение

    
    gets(WMess);  

        
    if (!WriteFile(hNamedPipe, WMess, sizeof(WMess), &cbWritten, NULL)) {
        quit(hNamedPipe);
        getch();
        return 0;
    }
                

            if(ReadFile(hNamedPipe, RMess, sizeof(RMess), &cbRead, NULL))
                 printf("\n Sent  message: %ch", RMess);
             else
             {
                printf("ReadFile: Oshibka ");
                printf("%ld\n", GetLastError());
                quit(hNamedPipe);
                getch();
                return 0;
             }
    
        
    printf("\n");

    quit(hNamedPipe);
    getch();
    return 0;

}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Клиент:

#include <conio.h>
#include <stdio.h>
#include <windows.h>

#define BUFFER_SIZE 1024 //1k

void error(HANDLE hNamedPipe) {

    printf("%ld\n", GetLastError());
    CloseHandle(hNamedPipe);
    printf("\nПроцесс завершен. Нажмите любую клавишу...");

}


int main() {

    char    szPipeName[256];                // Буфер для имени канала Pipe
    HANDLE    hNamedPipe;                // Идентификатор канала Pipe
    DWORD    cbWritten;                // Количество байт, переданных через канал
    DWORD    cbRead;                    // Количество байт, принятых через канал
    
    char WMess[BUFFER_SIZE];                    // написанное сообщение
    char RMess[BUFFER_SIZE];                    // полученное сообщение
    

    strcpy(szPipeName, "\\\\.\\pipe\\$MyPipe$");

    // Создаем канал с процессом PIPES
    hNamedPipe = CreateFile(szPipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

    // Если возникла ошибка, выводим ее код и завершаем работу приложения
    if(hNamedPipe == INVALID_HANDLE_VALUE) {
        printf("CreateFile: Ошибка ");
        error(hNamedPipe);
        getch();
        return 0;
    }

    // Выводим сообщение о создании канала
    printf("Соединение установлено...\n");
    

    gets(WMess);  

        
    if (!WriteFile(hNamedPipe, WMess, sizeof(WMess), &cbWritten, NULL)) {  ///вот тута вопрос...если на сервере отправленное сообщение было WMess...то тут будет наоборот??
        error(hNamedPipe);
        getch();
        return 0;
    }
                

            if(ReadFile(hNamedPipe, RMess, sizeof(RMess), &cbRead, NULL))
                 printf("\n Sent  message: %ch", RMess);
            else
            {
                printf("ReadFile: Ошибка ");
                printf("%ld\n", GetLastError());
                error(hNamedPipe);
                getch();
                return 0;
            }
    
        
    printf("\n");
    
    CloseHandle(hNamedPipe);
    printf("\nПроцесс завершен. Нажмите любую клавишу...");
    getch();
    return 0;

}

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Автор: EnergoHokum 24.10.2007, 14:59
Первое, что бросается в глаза - у тебя и на клиенте и на сервере одновременно идут запись, потом так же чтение. Разверни у кого-нить, чтобы получилось сервер->запись && клиент->чтение ___ сервер->чтение && клиент->запись.
А вообще (IMHO) лучше создать два pipe - один для записи, второй для чтения. Так не будет конфликтов.

Автор: weirdo 24.10.2007, 18:34
Я могу вообще использовать универсальную функцию как в сервере так и в клиенте CallNamedPipe:

BOOL CallNamedPipe(
LPCTSTR lpNamedPipeName, // адрес имени канала
LPVOID lpOutBuffer, // адрес буфера для записи
DWORD nOutBufferSize, // размер буфера для записи
LPVOID lpInBuffer, // адрес буфера для чтения
DWORD nInBufferSize, // размер буфера для чтения
LPDWORD lpBytesRead, // адрес переменной для записи
// количества прочитанных байт данных
DWORD nTimeOut); // время ожидания в миллисекундах

НО!!!! я не знаю что вписать в lpOutBuffer и lpInBuffer и lpBytesRead....может сталкивался с таким???

Автор: EnergoHokum 25.10.2007, 07:28
Так, значитЪ, из MSDN: CallNamedPipe выполняет соединение на named pipe (и ожидаает её instance, не знаю, как это корректно перевести), выполняет запись/чтение и закрывает эту pipe. Т. е. эту функцию ты можешь использовать только с одной стороны, т. к. установить, что сначала нужно делать (читать или писать) для неё невозможно. Дальше: lpInBuffer - указатель на буфер приёма, lpOutBuffer - указатель на буфер передачи, lpBytesRead - указатель на переменную, в которую пишется количество принятых байтов (char-ов).

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)