Bonsoir,

Je dois dans mon projet, réalisé un serveur dans une interface graphique QWidget.
Afin de rendre la fenêtre utilisable et ne pas freeze lorsque le serveur est en attente de connexion, je me suis tourné vers les Thread.

Après adaptation du code d'un camarade, j'en suis arrivé à ce code ci:


- Classe principale contenant le thread bluetooththread.h:

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
#ifndef BLUETOOTHTHREAD_H
#define BLUETOOTHTHREAD_H
 
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <iostream>
#include <initguid.h>
#include <WinSock2.h>
#include <ws2bth.h>
#include <bthsdpdef.h>
#include <BluetoothAPIs.h>
#include <Windows.h>
#include <strsafe.h>
#include <lmerr.h>
#include <string>
#include <cstring>
#include <fcntl.h>
 
using namespace std;
 
typedef ULONGLONG QWORD;
typedef ULONGLONG BT_ADDR, BTH_ADDR, bt_addr, btAddr, BTH_ADDR_SOCKADDR_BTH, pAddr;
 
DEFINE_GUID(SAMPLE_UUID, 0x31b44148, 0x041f, 0x42f5, 0x8e , 0x73, 0x18, 0x6d, 0x5a, 0x47, 0x9f, 0xc9);
DEFINE_GUID(  NULL_UUID, 0x0,        0x0,    0x0,    0x0 ,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0,  0x0);
 
class BluetoothThread;
 
 
struct thread_param{
       BluetoothThread* ser;
       SOCKET soc;
       SOCKADDR *pAdd;
};
 
class BluetoothThread
{
private:
    SOCKET          ListeningSocket;
    bool            running;
    SOCKADDR        *pAddr;
    DWORD           ClientThread(SOCKET,SOCKADDR*);
    SOCKADDR_BTH    address;
 
    int             length, nombre_co;
    char            buffer[1024];
    string          mess_retrn;
 
 
public:
    ~BluetoothThread();
    BluetoothThread();
    int           init();
    int           start ();
    int           pause ();
 
 
static DWORD WINAPI ThreadLauncher(void *p)
{
        struct thread_param *Obj = reinterpret_cast<struct thread_param*>(p);
        BluetoothThread *s = Obj->ser;
        //return s->ClientThread(Obj->soc, Obj->pAdd);
        return s->ClientThread(Obj->soc, Obj->pAdd);
 }
};
 
#endif // BLUETOOTHTHREAD_H
- bluetooththread.cpp associé

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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include "bluetooththread.h"
 
BluetoothThread::BluetoothThread(){
    running	= false;
}
 
int BluetoothThread::init(){
    WSADATA         m_data;
    WORD wVersionRequested = 0x202;
    nombre_co = 0;
 
    if(WSAStartup(wVersionRequested, &m_data ) != 0 ){
        cerr <<"/!\\  WSAStartup() : ECHEC  /!\\"<< endl;
        return 1;
    }
 
    address.addressFamily = AF_BTH;
    address.btAddr = 0;
    address.serviceClassId = NULL_UUID;
    address.port = BT_PORT_ANY;
    pAddr = (sockaddr*)&address;
 
    cout << "!--  Server correctement initialise  --!" << endl;
 
    return 0;
}
 
 
int BluetoothThread::start (){
    struct thread_param         p;
    HANDLE          hProcessThread;
    WSAPROTOCOL_INFO protocolInfo;
    int protocolInfoSize, size;
 
    if( ( ListeningSocket = socket( AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM ) ) == INVALID_SOCKET ){ // creer socket d'ecoute
        cout << "/!\\  Ne peut creer la socket. Erreur n°" << WSAGetLastError()<< "  /!\\"<<  endl;
        WSACleanup();
        return 1;
    }else{
        cout << "!-- Creation socket d'ecoute reussie --!" <<endl;
    }
 
    protocolInfoSize = sizeof(protocolInfo);
 
    if (getsockopt(ListeningSocket, SOL_SOCKET, SO_PROTOCOL_INFO, (char*)&protocolInfo, &protocolInfoSize) != 0)
    {
      exit(1);
    }
 
    if( bind( ListeningSocket, pAddr, sizeof(SOCKADDR_BTH) ) == SOCKET_ERROR ){
        cout << "/!\\  Bind() : ECHEC (" << WSAGetLastError() << ")  /!\\" << endl;
        closesocket( ListeningSocket );
        WSACleanup();
        return 1;
    }else{
        cout << "!--        Liaison effectuee         --!" << endl;
        length = sizeof(SOCKADDR_BTH) ;
        getsockname(ListeningSocket,(sockaddr*)&address,&length);
        wprintf (L"\nAppareil Bluetooth local = %04x%08x \nChannel du serveur = %d\n\n", GET_NAP(address.btAddr), GET_SAP(address.btAddr), address.port);
    }
 
    size = sizeof(SOCKADDR_BTH);
    if (getsockname(ListeningSocket, pAddr, &size) != 0)
    {
        cout << "/!\\ getsockname() : ECHEC (" << WSAGetLastError()<< " /!\\"<<  endl;
    }
 
    if( listen( ListeningSocket, 10 ) == SOCKET_ERROR ){
        cout << "/!\\  Listen() : ECHEC (" << WSAGetLastError() << ")  /!\\" << endl;
        closesocket( ListeningSocket );
        WSACleanup();
        return 1;
    }else{
        cout << "!--          Listen  reussi          --!"<< endl;
    }
 
 
    cout << "Socket : " << ListeningSocket << endl;
 
 
    p.ser = this;
    p.soc = ListeningSocket;
    p.pAdd = pAddr;
    hProcessThread = CreateThread(NULL, 0,&BluetoothThread::ThreadLauncher, &p,0,NULL);
 
    if ( hProcessThread == NULL ){
        cerr << "/!\\  CreateThread() : ECHEC (" <<GetLastError() << ")  /!\\" << endl;
    }
 
    return 0;
}
 
 
DWORD BluetoothThread::ClientThread(SOCKET soc, SOCKADDR *pAdd)
{
    WSAQUERYSET     service;
    CSADDR_INFO     csAddr;
    int             ilen, nbAdd, compteur;
    SOCKADDR_BTH    sab2;
    SOCKET          NewConnection;
 
    cout << "!--      Thread client demarre       --!" << endl;
 
    cout << "Socket : " << soc << endl;
 
    if (closesocket(soc) == SOCKET_ERROR) {
        cout << "!--          Erreur  socket          --!" << endl;
    }
 
    memset(&service, 0, sizeof(service));
    service.dwSize = sizeof(service);
 
    GUID serviceID = SAMPLE_UUID ;                            // PLANTE LE WSASetService(...)
    service.lpServiceClassId = (LPGUID) &serviceID ;
    service.dwNumberOfCsAddrs = 0 ;
    //GUID serviceID = OBEXFileTransferServiceClass_UUID;
    //service.lpServiceClassId = &serviceID ;
    //service.dwNumberOfCsAddrs = 1 ;
    service.dwNameSpace = NS_BTH ;
 
    memset(&csAddr, 0, sizeof(csAddr));
    csAddr.LocalAddr.iSockaddrLength = sizeof(SOCKADDR_BTH);
    csAddr.LocalAddr.lpSockaddr = pAdd;
    csAddr.iSocketType = SOCK_STREAM;
    csAddr.iProtocol = BTHPROTO_RFCOMM;
    service.lpcsaBuffer = &csAddr;
 
    /*if(WSASetService(&service, RNRSERVICE_REGISTER, 0) == SOCKET_ERROR)
    {
        cout << "/!\\  WSASetService() enregistrement : ECHEC (" << WSAGetLastError() << ")  /!\\" << endl;
    }else{
        cout << "!-- Service enregistrement effectue  --!" << endl;
    }*/
 
    running = true;
    ilen = sizeof(sab2);
 
    while(running)
    {
        if( (NewConnection = accept( soc, (struct sockaddr*)&sab2, &ilen)) == INVALID_SOCKET )
        //if((NewConnection = accept( this->ListeningSocket, 0, &ilen)) == INVALID_SOCKET)
        {
            cout  << "/!\\     Accept() : ECHEC (" << WSAGetLastError() << ")     /!\\" << endl;
            closesocket( soc );
            WSACleanup();
            return 1;
        }
        else
        {
            wprintf (L"\nConnection entrante de : %04x%08x par le channel : %d\n", GET_NAP(sab2.btAddr), GET_SAP(sab2.btAddr), sab2.port);
            memset(buffer, 0, sizeof(buffer));
 
            recv(NewConnection,(char*)buffer,1, 0);
 
            nbAdd=(int)buffer[0];
            cout << "Nombre de boucles : " << (int)buffer[0] << endl << endl;
            send(NewConnection, "Bien recu !", 50, 0);
 
            for(compteur=0; compteur<nbAdd; compteur++)
            {
                nombre_co++;
                recv(NewConnection,(char*)buffer, sizeof(buffer), 0);
                cout << "- Retour " << compteur+1 << ": " << buffer << endl;
            }
 
            closesocket(NewConnection);
        }
    }
 
    if (WSASetService(&service, RNRSERVICE_DELETE, 0) == SOCKET_ERROR)
    {
        cout  << "/!\\  WSASetService() fermeture : ECHEC (" << WSAGetLastError() << ")  /!\\" << endl;
    }
 
    ExitThread(0);
 
    return 0;
}
 
BluetoothThread::~BluetoothThread()
{
    shutdown(ListeningSocket,2);
}
 
/*int tcpserveur_thread::pause (){
    running = false;
    cout << "Serveur en pause" << endl;
    closesocket( ListeningSocket );
    return 0;
}*/
- widget.cpp

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
#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_start_button_clicked()
{
    _bth = new BluetoothThread();
 
    if(_bth->init()!=0)
    {
        cerr << "ne peut initialiser le serveur"<< endl;
    }
 
    if(_bth->start()!=0)
    {
        cerr << "ne peut demarrer le serveur"<< endl;
    }
}
(le widget.h ne contient qu'un pointeur vers la classe BluetoothThread et le slot du QPushButton permettant la mise en route du serveur)

Le problème, c'est que la socket et les paramètres (en général) que je donne au thread ne sont pas pris en compte comme le montre les deux valeurs différentes lors de l'affichage du socket (au début du thread et après sa création dans le start()).

Pourriez-vous m’éclaircir, merci !