Bonjour,

Je poste ici en désespoir de cause. En fait, ca fait une journée que je bloque sur des bizarreries du programme que j'ai fait.

Voilà l'idée du prog. Je scanne un dossier et dès qu'un fichier texte arrive, je l'envoie à un serveur. Je mets du multithread là-dedans pour gérer plus facilement l'arrivée simultanée de plusieurs fichiers.

Maintenant, les problèmes. Primo, le programme semble marcher. Mais, il se passe deux trucs bizarres.

- Primo : quand je lance le programme et que je balance d'un coup plusieurs fichiers txt dans le dossier, il lui arrive parfois de n'en voir qu'un seul (c'est très aléatoire). Tous les autres fichiers copiés après sont parfaitement détectés.

- Segundo : Quand un fichier texte est détecté, j'appelle la fonction newFile(). Cette fonction récupère le nom du fichier et crée un thread pour envoyer le fichier. Or, alors que je suis certain (printf à l'appui) que newFile() est appelé qu'un seule fois pour un fichier donné, il arrive (parfois aussi) que le fichier soit envoyé plusieurs fois ; ce que j'attribue peut-être à tord à un problème avec mes threads ....


Mais moi, ça me semble correct. Il doit bien sûr avoir des choses qui vont pas dans mon code, mais mon niveau en C me permet pas de trouver le pb.

Donc, je vous colle le code, désolé d'être aussi brutal.
Et merci d'avance à ceux qui auront la patience de m'aider.


Code : Sélectionner tout - Visualiser dans une fenêtre à part
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <win_scan_send.h>

int main(int argc, char *argv[]) {

    BOOL bResult;
    HANDLE hDir;
    BYTE Buf[10000];
    DWORD RetBytes;
    FILE_NOTIFY_INFORMATION *pInfo;
    DWORD i = 0;
    

    // ouverture du dossier
    hDir = CreateFile(
            PATH_CLIENTE,
            FILE_LIST_DIRECTORY,
            FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
            NULL,
            OPEN_EXISTING,
            FILE_FLAG_BACKUP_SEMANTICS,
            NULL);

     while(1) {
        // on attend des modifs dans le dossier
        bResult = ReadDirectoryChangesW(
            hDir,
            Buf,
            10000,
            FALSE,
            FILE_NOTIFY_CHANGE_FILE_NAME,
            &RetBytes,
            NULL,
            NULL);

        // lecture des modifs dans le dossier
        pInfo = (FILE_NOTIFY_INFORMATION *)&Buf[i];
        
        switch(pInfo->Action) {
            case FILE_ACTION_ADDED: 
                NewFile(pInfo);
                break;
        }

        while ((i = pInfo->NextEntryOffset) != 0) {
            pInfo = (FILE_NOTIFY_INFORMATION *)&Buf[i];
            switch(pInfo->Action) {
                case FILE_ACTION_ADDED: 
                    NewFile(pInfo);
                    break;
            }
        }
     }

    // fermeture dossier
    CloseHandle(hDir);



    return 1;
}


/* ------------------------------------------------------- */


int NewFile(FILE_NOTIFY_INFORMATION *pInfoFic) {
// traitement nouveau fichier
// si c'est un '.txt', création thread pour envoi au serveur

    WCHAR * fileName;
    DWORD ThreadId;

    // on récupère le nom du fichier
    fileName = malloc (pInfoFic->FileNameLength + sizeof(WCHAR) );
    memcpy(fileName, pInfoFic->FileName,pInfoFic->FileNameLength);
    fileName[pInfoFic->FileNameLength / sizeof(WCHAR)] = '\0';

    if ( (fileName[pInfoFic->FileNameLength / sizeof(WCHAR) - 4] == '.') && (fileName[pInfoFic->FileNameLength / sizeof(WCHAR) - 3] == 't') && (fileName[pInfoFic->FileNameLength / sizeof(WCHAR) - 2] == 'x') && (fileName[pInfoFic->FileNameLength / sizeof(WCHAR) - 1] == 't') ) {
        // si c'est un '.txt', on envoi le fichier
        wprintf(L"envoi %s\n",fileName);
        CreateThread(NULL,(DWORD)NULL,ThreadProc,fileName,(DWORD)NULL,&ThreadId);
        return 0;
    } else {
        free(fileName);
    }

    return 0;
}


/* ------------------------------------------------------- */


DWORD WINAPI ThreadProc(LPVOID fileName) {
// Thread qui envoie les fichiers .txt

        WSADATA wsaData;
    HANDLE hFile;
        int res,my_socket;
    char path[3*FILE_BUFSIZE]= PATH_CLIENTE,file[FILE_BUFSIZE];
        char *adresse = ADRESSE_SEND; //direction IP serveur
        struct sockaddr_in adresse_socket;
    
    /* ouverture du fichier*/
    WideCharToMultiByte(CP_ACP,0,fileName,wcslen(fileName),file,FILE_BUFSIZE,0,0);
    strcat(path,"\\");
    strcat(path,file);
    hFile = CreateFile(path,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    // si il y a un pb à l'ouverture du fichier, on attend 50ms et on réessaye
    // si il y a de nouveau un problème, on abandonne
    if(hFile == INVALID_HANDLE_VALUE) {
        Sleep(50);
        hFile = CreateFile(path,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        if(hFile == INVALID_HANDLE_VALUE) {printf("skip file\n"); return 0;}
    }
    
    /* initialisation winsock 2.0 */
    if((res = WSAStartup(MAKEWORD(2,0), &wsaData)) != 0)
        printf("Impossible d'initialiser l'API Winsock 2.0\n");

    /* creation de la socket sur un port quelconque (0) */
    if((my_socket = socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
        printf("Echec de création de la socket !\n");

    memset(&adresse_socket,0x0,sizeof(adresse_socket)); 


    /* preparation adresse serveur */
    adresse_socket.sin_family = AF_INET;
    adresse_socket.sin_port = htons(PORT_SEND);
    adresse_socket.sin_addr.S_un.S_addr = inet_addr(adresse);

    /* connection au serveur */
    if((res = connect(my_socket,(struct sockaddr *) &adresse_socket,sizeof(adresse_socket))) != 0)
        printf("Impossible de se connecter !\n");

    /* envoi du nom du fichier */
    if (send(my_socket,file,sizeof(file),0)==SOCKET_ERROR) {
        printf("pb envoi nom du fichier\n");
    }

    /* envoi fichier */
    if (!TransmitFile(my_socket,hFile,0,0,NULL,NULL,TF_DISCONNECT)) printf("pb envoi fichier : %d\n",GetLastError());
    else printf("fichier %s envoye\n",file);

    /* fermeture socket et fichier */
    close(my_socket);
    CloseHandle(hFile);

    free(fileName);
    return 0;

}
Note : je suis conscient qu'il y a des trucs qui ne sont pas du tout optimisés mais là n'est pas l'objectif pour l'instant