Bonjour tout le monde, ca fait deux jours que je suis bloque la dessus, je commence un peu a désespérer peut être que ça vous sautera aux yeux sait on jamais??

Voila j'écris un petit programme tout bête qui fait une addition de façon répartie (chaque client/serveur a un double, et il doit additionner le sien avec ceux de tous ses voisins (dont leur ip/port est donné dans un fichier texte.

Mon problème est le suivant:
lorsque mon client se connecte aux serveurs un par un de façon séquentielle il y arrive parfaitement et l'addition se fait comme il faut.
Le problème est que cela est complètement inneficace et que je perds trop de temps dans les appels bloquants (ex. : un serveur ne répond pas...).

La solution logique à ce problème est d'utiliser des threads (pthreads), de telle façon que mon client va contacter tour à tour chacun de ses voisins en utilisant un thread par connection.

Mais le problème est justement la!!
La connection se passe bien, mais au moment de l'appel de la fonction recv(), je recois la valeur 0, ce qui veut dire que le serveur a coupé la connection de l'autre coté, et pourtant je n'appelle pas la commande close...

Voila si vous pouviez jeter un coup d'oeil ca m'aiderait vraiment beaucoup, les méthodes intéréssantes sont setServerSocket() et retrieveNextNode().

Merci d'avance

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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
 
#include "peer.h"
using namespace std;
 
 
 
peer* signalHandler;
 
// Constructor for lru.
peer::peer(char* fileName) {
  _fileName = fileName;
  _peerNumber = 0;
  _sum = 0;
  pthread_mutex_init(&_mutex, NULL);
 
  // Creates a new thread that will listens for incoming connections.
  pthread_create(&_serverThread, NULL, peer::setServer, (void*) this);
 
  // We set the global variable signal handler so that the static function
  // will know which object to use to handle the alarm signal.
  signalHandler = this;
  // Sets the alarm signal handler.
 
 
  // Parses the given input file.
  parseInputFile();
 
  _iterator = _neighborList.begin();
}
 
 
// Sets up the server socket
void peer::setServerSocket() {
  // Sets up the socket.
  struct addrinfo hints;
  struct addrinfo *res;
 
  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE; // Sets my ip adddress.
  getaddrinfo(NULL, "1030", &hints, &res);
 
  // Make a socket.
  int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 
  // Bind the socket to the right port.
  bind(sockfd, res->ai_addr, res->ai_addrlen);
 
  // Listen.
  listen(sockfd, 10);
 
  while(1) {
    struct sockaddr_storage their_addr;
    socklen_t addr_size = sizeof their_addr;
 
    int newSocket;
    newSocket = accept(sockfd, (struct sockaddr*) &their_addr, &addr_size);
 
    // MAYBE WE NEED TO CREATE ANOTHER THREAD HERE.
    char tosend[50];
    sprintf(tosend,"%g", _inputValue);
    // Send it.
 
    send(newSocket, tosend, strlen(tosend), 0);
 
    // Close the sending socket.
    // close(newSocket);
  }
}
 
// Adds its own sum, and then contacts all the other neighbors to 
// add sequentially their data.
void peer::computeSum() {
  _sum += _inputValue;
  _peerNumber++;
 
  while (_iterator != _neighborList.end()) {
    pthread_t thread;
    // Creates a new thread that will launch the function retrieveNextNode.
 
    pthread_create(&thread, NULL, peer::retrieve_func, (void*) this);
    // retrieveNextNode();
    // Next time we call retrieveNextNode, will be ready.
    _iterator++;
  }
}
 
// Connects to the next node and retrieves its data and try to add it, disconnects when done.
void peer::retrieveNextNode() {
  string ipAddress = _iterator->getIp();
  string port = _iterator->getPort();
 
  // Sets up the socket.
  struct addrinfo hints;
  struct addrinfo *res;
 
  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  getaddrinfo("localhost", "1030", &hints, &res);
  //  getaddrinfo(ipAddress.c_str(), port.c_str(), &hints, &res);
 
  // Make a socket.
  int sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
 
  // Connect.
  if (connect(sockfd, res->ai_addr, res->ai_addrlen)!= 0) {
    cerr << "Error on connection" << endl;  
    return;
  }
 
  // Read the value sent by the other host, and add it to the sum.
  char msgReceived[50];
  int len = strlen(msgReceived);
  recv(sockfd, msgReceived, len, 0);
 
  // Critical section, updates the sum and the number of peers.
  pthread_mutex_lock(&_mutex);
  _sum += atof(msgReceived);
  _peerNumber++;
  pthread_mutex_unlock(&_mutex);
 
  // Close the connection to this neighbor.
  close(sockfd);
}
 
void catch_alarm(int sig_num) {
  signalHandler->printOutput();
}
 
peer::~peer() {
 
}
 
// Parses the input file and puts all the data in data structures.
void peer::parseInputFile() {
  _inputFile.open(_fileName);
  string inputValue = getNextLine();
  _inputValue = atof(inputValue.c_str());
 
  string threashold = getNextLine();
  _threashold = atoi(threashold.c_str());
  startTimer();
 
  // THERE IS A PROBLEM WITH PARSING HERE
  _port = getNextLine();
  // string::iterator it = _port.end() - 1;
  // _port.erase(it);
  //cout << strlen(_port.c_str());
 
  parseNeighborList();
}
 
// Starts the timer with the indicated threashold.
void peer::startTimer() {
  alarm(_threashold);
}
 
void peer::parseNeighborList() {
  while (!_inputFile.eof()) {
    string neighbor = getNextLine();
    if (!neighbor.empty()) {
      size_t colonSeparator = neighbor.find(":");
 
      string ipAddress = neighbor.substr(0, colonSeparator);
 
      string port = neighbor.substr(colonSeparator+1, neighbor.length() - colonSeparator - 2);
      peerAddress toAdd(ipAddress, port);
      _neighborList.push_back(toAdd);
    }
  }
}
 
// Returns the next non empty line.
string peer::getNextLine() {
  // We loop until we find a non empty line.
  string trimmed;
  do {
    _inputFile.getline(_buffer, 256);
    trimmed = trimLine(_buffer);
  } while(trimmed.length() == 1 && !_inputFile.eof()); 
  return trimmed;
}
 
string peer::trimLine(const char* toTrim) {
  string trimmed = string(toTrim);
  // Trims the white spaces.
  remove(trimmed.begin(), trimmed.end(), ' ');
  return trimmed;
}
 
void peer::printOutput() {
  printf("%f\t%d\n", _sum, _peerNumber);
}
 
void peer::printDebug() {
  cout << "Input value: " << _inputValue << endl;
  cout << "Time threashold: " << _threashold << endl;
  cout << "Port: " << _port << endl;
  cout << "Neighbors list: " << endl;
  list<peerAddress>::iterator it;
  for (it = _neighborList.begin(); it != _neighborList.end(); it++) {
    cout << "Ip: " << it->getIp() << ", port: " << it->getPort() << endl;
  }
}
 
int main(int argc, char **argv)
{
  // The text file name is given as an input.
  if(argc != 2) {
    fprintf(stderr,"usage: peer <filename>\n");
    exit(1);
  }
  signal(SIGALRM, catch_alarm);
  peer myPeer(argv[1]);
  myPeer.printDebug();
  myPeer.computeSum();
  pthread_exit(NULL);
  return 0;
}
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
 
#ifndef PEER_H
#define PEER_H
 
#include <list>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <csignal>
#include <pthread.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <netdb.h>
#include <cassert>
#include <signal.h>
#include <netinet/in.h>
#include "peerAddress.h"
 
class peer {
 
  static void* retrieve_func(void* d) {
    ((peer*) d)->retrieveNextNode();
    return NULL;
  }
 
  static void* setServer(void* d) {
    ((peer*) d)->setServerSocket();    
    return NULL;
  }
 
 private:
  char* _fileName;
  char _buffer[256];
  std::ifstream _inputFile;
  double _inputValue;
  int _threashold;
  std::string _port;
  int _peerNumber;
  double _sum;
  pthread_mutex_t _mutex;
  std::list<peerAddress> _neighborList;
  std::list<peerAddress>::iterator _iterator;
 
  pthread_t _serverThread;
  // Server socket --> listener (will need to create other when incoming connections.
  int s;
 
 public:
  peer(char* fileName);
  ~peer();
  void parseInputFile();
  void parseNeighborList();
  std::string trimLine(const char* toTrim);
  std::string getNextLine();
  void printOutput();
  void startTimer();
  void printDebug();
  void computeSum();
  void retrieveNextNode();
  void setServerSocket();
};
 
#endif

Merci encore!!