1
votes

i'm traing to do 2 process that do this:

Process A (the client) : - It opens a temporary file for writing (use GetTempFileName to obtain a unique file name). - It starts Process B passing as argument the name of the file. - It reads from standard input strings of characters, and it writes those strings on the intermediate file. Use string of constant length (e.g., #define MAX_LEN 100). - It stops reading strings from standard input when it receives an end-of-file (ctrl-Z). - Before terminating, it writes the string ".end" as last line of the file.

Process B (the server) works as follows: - It opens the intermediate file for reading. - It reads lines as soon as they are available, and it prints them out on standard output.

  • Process A keeps the file open, and it always locks the next part of the file before unlocking the previous part.
  • Process B runs in parallel, and it reads a shared file, waiting to have access to single lines to read them.

but seams that the ReadFile on process B do not wait until the fileLock is removed so it terminate befor the first line is inserted

process A:

#include <windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <io.h>

#define MAX_LEN 100



int _tmain(int argc, LPTSTR argv[]){


    TCHAR tmpFileName[MAX_PATH];
    TCHAR tmppath[MAX_PATH];
    TCHAR moment[MAX_PATH];
    TCHAR command[MAX_PATH + 256];
    UINT uRetVal = 0;
    HANDLE bufferW,next;
    DWORD n;
    PROCESS_INFORMATION piS;
    STARTUPINFO siS;
    TCHAR buffer[MAX_LEN];
    int i=0;


    OVERLAPPED ov = { 0, 0, 0, 0, NULL };
    LARGE_INTEGER FilePos;


    ZeroMemory(&siS, sizeof(siS));
    siS.cb = sizeof(siS);
    ZeroMemory(&piS, sizeof(piS));





    uRetVal = GetTempFileName(_T("."), // directory for tmp files
        _T(""),     // temp file name prefix 
        0,                // create unique name 
        tmpFileName);  // buffer for name 

    if (uRetVal == 0)
    {
        _tprintf("\n errore apertura temp file");
        return (3);
    }


    GetCurrentDirectory(MAX_PATH, moment);
    //_stprintf(tmppath, "%s\\ %s",moment,tmpFileName);
    _tprintf("\n CLIENT PATH %s  \n",moment);



    //_stprintf(command,"%s %s","C:\\Users\\zio gianni\\Documents\\Visual Studio 2013\\Projects\\lab11server\\Debug\\lab11server.exe",tmpFileName);
    _stprintf(command, "%s %s", "server.exe", tmpFileName);
    bufferW = CreateFile(tmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    next = CreateFile(tmpFileName, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (next == INVALID_HANDLE_VALUE) {

        _tprintf(_T("Cannot open client file. Error: %x\n"),
            GetLastError());
        _tprintf(" \n Nome File: %s\n", "./prova.bin");
        return 2;
    }
    if (bufferW == INVALID_HANDLE_VALUE) {

        _tprintf(_T("Cannot open client file. Error: %x\n"),
            GetLastError());
        _tprintf(" \n Nome File: %s\n", "./prova.bin");
        return 2;
    }


    FilePos.QuadPart = i*MAX_LEN * sizeof (TCHAR);
    ov.Offset = FilePos.LowPart;
    ov.OffsetHigh = FilePos.HighPart;
    ov.hEvent = 0;


    LockFileEx(bufferW, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
    printf("file bloccato avvio server con comand: %s\n", command);



    if (!CreateProcess(NULL,   // No module name (use command line)
        command,        // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        TRUE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &siS,            // Pointer to STARTUPINFO structure
        &piS)           // Pointer to PROCESS_INFORMATION structure
        )
    {
        printf("CreateProcess failed (%d).\n", GetLastError());
        return -5;
    }


    while (TRUE){



        scanf("%s",buffer);
        if (strcmp(buffer, "EOF")==0){

            break;
        }

        WriteFile(bufferW, buffer, MAX_LEN*sizeof(TCHAR), &n, NULL);


        FilePos.QuadPart =(i+1)* MAX_LEN * sizeof (TCHAR);
        ov.Offset = FilePos.LowPart;
        ov.OffsetHigh = FilePos.HighPart;
        ov.hEvent = 0;

        if (i % 2 == 0){

            LockFile(next, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
            FilePos.QuadPart = (i )* MAX_LEN * sizeof (TCHAR);
            ov.Offset = FilePos.LowPart;
            ov.OffsetHigh = FilePos.HighPart;
            ov.hEvent = 0;
            UnlockFile(bufferW, 0, 0, 0, &ov);
        }
        else{

            LockFile(bufferW, LOCKFILE_EXCLUSIVE_LOCK, 0, FilePos.LowPart, FilePos.HighPart, &ov);
            FilePos.QuadPart = (i )* MAX_LEN * sizeof (TCHAR);
            ov.Offset = FilePos.LowPart;
            ov.OffsetHigh = FilePos.HighPart;
            ov.hEvent = 0;
            UnlockFile(next, 0, 0, 0, &ov);
        }

        i++;
    }



    sprintf(buffer, ".end");

    WriteFile(bufferW, buffer, MAX_LEN*sizeof(TCHAR), &n ,NULL);


if (i % 2 == 0){


        FilePos.QuadPart = (i)* MAX_LEN * sizeof (TCHAR);
        ov.Offset = FilePos.LowPart;
        ov.OffsetHigh = FilePos.HighPart;
        ov.hEvent = 0;
        UnlockFile(bufferW, 0, FilePos.LowPart, FilePos.HighPart, &ov);
    }
    else{


        FilePos.QuadPart = (i)* MAX_LEN * sizeof (TCHAR);
        ov.Offset = FilePos.LowPart;
        ov.OffsetHigh = FilePos.HighPart;
        ov.hEvent = 0;
        UnlockFile(next, 0, FilePos.LowPart, FilePos.HighPart, &ov);
    }

    // Wait until child process exits.
    WaitForSingleObject(piS.hProcess, INFINITE);

    // Close process and thread handles. 
    CloseHandle(piS.hProcess);
    CloseHandle(piS.hThread);


    return 0;
}

process B:

#include <windows.h>
#include <process.h>
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <io.h>

#define MAX_LEN 100


int _tmain(int argc, LPTSTR argv[]){

    HANDLE read;
    DWORD n;
    int i = 0;
    TCHAR buffer[MAX_LEN], path[MAX_LEN];
    OVERLAPPED ov = { 0, 0, 0, 0, NULL };
    LARGE_INTEGER FilePos;

    read = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (read == INVALID_HANDLE_VALUE) {

        _tprintf(_T("Cannot open input file. Error: %x\n"),
            GetLastError());
        _tprintf(" \n Nome File: %s\n", argv[1]);
        return 2;
    }
    _tprintf(" \n Nome File APERTO: %s\n", argv[1]);

GetCurrentDirectory(MAX_LEN,path);
_tprintf(" \n path server: %s\n%s\n", path,argv[1]);



while (ReadFile(read, buffer, MAX_LEN*sizeof(TCHAR), &n, &ov) && n>0 ){


    if (n == 0){
        fprintf(stderr,"error readfle\n");
        return -5;
    }
    if (strncmp(buffer, ".end", 4) == 0){
        _tprintf(" \n STAMPA SERVER: esco\n");
        break;
    }

    _tprintf(" \n STAMPA SERVER: %s\n", buffer);



}



if (n == 0){
    fprintf(stderr, "error readfle\n");
    return -5;
}
    _tprintf("\n END SERVER");
    return 0;
}
1
ReadFile will return 0 if there's no data left to read in the file, and you're exiting your loop at that point.Jonathan Potter
Why a file? A socket or a pipe would be a much simpler implementation, and it wouldn't have this problem.user207421
I do something similar to this in a service that produces a log file that a viewer app displays in real-time, but I don't use locks to control access to the file. The service opens the file for writing and the viewer opens the file for reading, then the service sends a signal to the viewer whenever a new record has been written to the file, and the viewer then queries the file size and only reads bytes that are new since the last read. Such a signal could be replaced with a timer or a file change notification from the OS instead.Remy Lebeau
@user3535936: why are you using TCHAR for your data buffer, but not using TCHAR APIs to receive input data into that buffer, and output data from that buffer? You do realize that this code will not even compile if you enable Unicode, don't you? And why are you sending the entire buffer instead of only the characters that the user actually entered?Remy Lebeau
i have to use a file because is a mandatory requirement . i cant use pipe i send the entire buffer because i need a fixed struct for use properle FileLock() it well be more complex to manage variable byte locking portion of the fileuser3535936

1 Answers

2
votes

Do not use actual files for inter process communication. Use named pipes!

Search for CreateNamedPipe, there are plenty of examples.