Je suis en train de coder un serveur udp en multithreading qui a pour but de recevoir des morceaux d'images de les stocker dans un tableau et lorsque ce tableau à l'ensemble des données décrivant l'image, on lance un thread de reconstruction (utilisation opencv).
Voici le code du serveur :
// server program for udp connection
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include<netinet/in.h>
#define PORT 5000 // c'est le port 300000 qui ne marche pas en udp
#define MAXLINE 1000
//lisa
#include <signal.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/videoio/videoio.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#define TAILLE_PACK 10000
#define N 4 // entête
#define CLI_MAX 50
#define varia 8
#define BUFFER_SIZE 50
#define T_max 5
//g++ -Wall -o srv udp_srv.cpp -lopencv_core -lopencv_highgui -lopencv_imgcodecs -lpthread
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
void* server(void* data1);
typedef struct
{
int index;
int longueur;
int client;
int cpt;
int *tab;
int cpt1;
int *tab_launch;
int *reponse;
int *thread_check;
}Donnee;
int img_ino[CLI_MAX][100000]; //plus tard pr alloc dynamique //segmentation fault à cause taille
// Driver code
int main()
{
clock_t time1[CLI_MAX]={0};
for (int i = 0;i<CLI_MAX;i++)
time1[i]=0;
struct timeval timeout={0,500}; //set timeout for 2 seconds
int info[N+TAILLE_PACK];
int tab[CLI_MAX][4];
int raz[CLI_MAX]={0};
int thread_cli[T_max]={0};
for(int i=0;i<CLI_MAX;i++) //init à une valeur diff de 0 mais innategnable
tab[i][1]=100;
short int cpt_img_f[CLI_MAX]={0};
int verif[CLI_MAX][100];
for(int i = 0;i<CLI_MAX;i++)
for (int j=0;j<100;j++)
verif[i][j]=0;
struct timespec now1,now2,now3,now4,now5,now6,now7,now8,now9,now10,now11,now12,now13,now14;
char strNow[ BUFFER_SIZE ];
int listenfd;
struct sockaddr_in servaddr, cliaddr;
bzero(&servaddr, sizeof(servaddr));
// Create a UDP Socket
listenfd = socket(AF_INET, SOCK_DGRAM, 0);
servaddr.sin_addr.s_addr = htonl(INADDR_ANY); //inet_addr("192.168.10.203");
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
// bind server address to socket descriptor
bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));
//setsockopt(listenfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(struct timeval));
//receive the datagram
socklen_t len;
len = sizeof(cliaddr); //len is value/result
int length=0;
int message_index = 0;
int r ;
int message;
int nb_msg ;
int end = 0;
int n;
unsigned long compteur_thread[T_max]={0};
struct sockaddr_in tab_addr[CLI_MAX];
clock_t ti,tf; //possibiliter de calculer temps d'envoie
Donnee p;
p.tab = (int*)malloc(T_max*sizeof(int)); // on alloue de la mémoire pour tab
p.cpt = 0;
p.thread_check = (int*)malloc(T_max*sizeof(int));
p.tab_launch = (int*)malloc(CLI_MAX*sizeof(int)); // on alloue de la mémoire pour tab
p.reponse = (int*)malloc(CLI_MAX*sizeof(int));
for(int h=0;h<CLI_MAX;h++)
{
p.tab_launch[h]=1;
p.reponse[h]=0;
}
int *return_value;
//on initialise les variables à 0
p.tab[0] = 0;
p.tab[1] = 0;
p.tab[2] = 0;
p.tab[3] = 0;
p.tab[4] = 0;
p.thread_check[0] = 0;
p.thread_check[1] = 0;
p.thread_check[2] = 0;
p.thread_check[3] = 0;
p.thread_check[4] = 0;
p.cpt1=0;
p.index=0;
pthread_t threads[T_max];
while(end == 0)
{
tf = clock();
n = recvfrom(listenfd, (int*)info, (N+TAILLE_PACK)*sizeof(int),MSG_WAITALL, (struct sockaddr*)&cliaddr,&len); //receive message from server
timeout={0,500}; // quand 2 clients arrivent successivement
setsockopt(listenfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(struct timeval)); // recvfrom non bloquant après 2 secondes
//printf("n %d\n",n);
if(n>=0) // i reçoit une data il l'a traite
{
ti = clock();
time1[info[0]]=ti; //heure du dernier msg reçu par client
//printf("msg received cleint %d temps %ld \n",info[0],time[info[0]]);
if(info[1]==0) //CAS RECEP LENGTH
{
//on recup la length
length = info[3];
//printf("\n length %d\n",length);
tab[info[0]][0]=length;
tab_addr[info[0]]=cliaddr;
r = length % TAILLE_PACK;
tab[info[0]][2]=r;
nb_msg = ((length-r)/TAILLE_PACK)+1; // surement +1 pour le reste
tab[info[0]][1]=nb_msg;
//printf("Calcul iteration client %d\n",nb_msg);
//on dit merci au client d'avoir envoyer sa trame de début
message = 300;
int t = sendto(listenfd, &message, sizeof(int), 0,(struct sockaddr*)&cliaddr, sizeof(cliaddr));
//printf("Ma structure : \n- AF_INET %lu \n- port %lu\n- struct in_addr %lu\n- sin_zero %s\n- in_addr %lu\n",cliaddr.sin_family,cliaddr.sin_port,cliaddr.sin_addr,cliaddr.sin_zero,cliaddr.sin_addr.s_addr);
// printf("adresse de début du tableau %d\ncliaddr %d tab_addr[i] %d\n",tab_addr,cliaddr,tab_addr[info[0]]);
// printf("Structure en param de tab_addr :\n- AF_INET %lu \n- port %lu\n- struct in_addr %lu\n- sin_zero %s\n- in_addr %lu\n",tab_addr[info[0]].sin_family,tab_addr[info[0]].sin_port,tab_addr[info[0]].sin_addr,tab_addr[info[0]].sin_zero,tab_addr[info[0]].sin_addr.s_addr);
timespec_get( &now1, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now1.tv_sec ) );
printf("%s.%09ld msg 1 : ON A RECU TRAME DE START \n",strNow,now1.tv_nsec);
printf("\n\n\n\n");
}
if((info[1]==1)&& (tab[info[0]][1]!=100)) //CAS RECEP DATA et pas msg de fin filtre les trames qui s'incruste
{
timespec_get( &now2, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now2.tv_sec ) );
printf("%s.%09ld msg 2 : index %d client %d\n",strNow,now2.tv_nsec,info[3],info[0]);
message_index = info[3];
if(message_index == nb_msg-1) // si on reçoit le reste
{
memcpy(&img_ino[info[0]][message_index*TAILLE_PACK],&info[4],(tab[info[0]][2])*sizeof(int)); // on stock dans tableau le reste et pas l'ensemble des data inutiles
/*for (int jean = 4;jean <tab[info[0]][2]+4;jean++)
printf("%d ",info[jean]);
printf("après le memcpy \n");
for(int elisa = 0;elisa<tab[info[0]][2];elisa++)
printf("%d ",img_ino[info[0]][info[3]*TAILLE_PACK+elisa]);*/
}
else
{
memcpy(&img_ino[info[0]][message_index*TAILLE_PACK],&info[4],TAILLE_PACK*sizeof(int)); // on stock ds tableau la data de 10 000
/*for (int jeanne = 4;jeanne <TAILLE_PACK+4;jeanne++)
printf("%d ",info[jeanne]);
printf("après le memcpy \n");
for(int marie = 0; marie <TAILLE_PACK;marie++)
printf("%d ",img_ino[info[0]][info[3]*TAILLE_PACK+marie]);*/
}
if ((verif[info[0]][message_index]==0)) // si c'est la 1er fois qu'on recoit cet index et qu'on a bien reçu la length au préalable
cpt_img_f[info[0]]+=1; // on incrémente le compteur d'image // le but est d'éliminer les trames parasites
verif[info[0]][message_index]=1; // on stock les index reçu
}
}
/*for(int b=0;b<T_max;b++)
{
printf("le thread %d est dans l'état %d\n",p.index,threads[p.index].std::thread::joinable());
}*/
// printf("avant boucle for tab[i][1] %d client courant %d \n",tab[info[0]][1],info[0]);
timespec_get( &now3, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now3.tv_sec ) );
printf("%s.%09ld msg 3 : CLI 3 raz %d cpt_img_f %d \n",strNow,now3.tv_nsec,raz[3],cpt_img_f[3]);
timespec_get( &now4, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now4.tv_sec ) );
printf("%s.%09ld msg 4 : CLI 2 raz %d cpt_img_f %d \n",strNow,now4.tv_nsec,raz[2],cpt_img_f[2]);
for(int i = 0;i<CLI_MAX;i++)
{
if((raz[i]!=1)&&(cpt_img_f[i]>0)) // si le client n'est pas encore éteint && qu'il a reçu au - 1 trame
{
//time_t now2 = time(&now2);
//printf("%ldh%ldm%lds cpt %d et tab %d client %d\n", (now2 / 3600) % 24, (now2 / 60) % 60, now2 % 60,cpt_img_f[i],tab[i][1],i);
if(cpt_img_f[i]==tab[i][1]) // si j'ai toutes les trames (cpt full img s'incrémente uniquement si il reçoit une trame différentes de la précédente)
{
timespec_get( &now5, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now5.tv_sec ) );
printf("%s.%09ld msg 5 : Reconstruction classique \n",strNow,now5.tv_nsec);
message = 100;
struct sockaddr_in var;
var = tab_addr[i];
int a = sendto(listenfd, &message, sizeof(int), 0,(struct sockaddr*)&var, sizeof(var)); // on envoie un message de fin pour dire au client qu'il peut se deco
time_t now4 = time(&now4);
//printf("%ldh%ldm%lds message envoyer au client %d valid ou non %d \n", (now4 / 3600) % 24, (now4 / 60) % 60, now4 % 60,i,a);
for(int i=0;i<T_max;i++)
{
if(p.tab[i]==0)
{
p.cpt1++;
p.index=i;
//printf("index choisi %d\n",p.index);
p.tab[i]=1;
break;
}
}
//RAZ
cpt_img_f[i]=0; // ici très important pour ne pas reconstruire l'image 2 fois au prochain tour de boucle
raz[i]=1;
// data à faire passer en paramètre du thread
p.client = i;
p.longueur = tab[i][0];
p.cpt++;
p.thread_check[p.index]=i; //tres important de le faire avant
int k = pthread_create(&threads[p.index], NULL, server, (void*) &p);
if(k != 0)
printf("error in creation of the thread %d error %d \n",p.index,k);
timespec_get( &now6, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now6.tv_sec ) );
printf("%s.%09ld msg 6 : le client %d a lancer le thread %d \n",strNow,now6.tv_nsec,i,p.index);
int j = pthread_detach(threads[p.index]);
if(j!=0)
printf("error dans le detachement du thread %d error %d\n",p.index,j);
}
if((tf-time1[i])>0) // si ça fait un petit bout de temps que le client n'a pas parler
{ // 500 à voir comment on le règle
timespec_get( &now7, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now7.tv_sec ) );
printf("%s.%09ld msg 7 : ON REGARDE CLI QUI N'ONT PAS PARLER DEPUIS LONGTEMPS\n",strNow,now7.tv_nsec);
timespec_get( &now8, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now8.tv_sec ) );
printf("%s.%09ld msg 8 : tf %d; ti %d; diff %d\n",strNow,now8.tv_nsec,tf,time1[i],tf-time1[i]);
timespec_get( &now9, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now9.tv_sec ) );
printf("%s.%09ld msg 9 : cpt %d tab %d cli %d \n",strNow,now9.tv_nsec,cpt_img_f[i],tab[i][1],i);
if(cpt_img_f[i]!=tab[i][1]) // si il manque 1 trame ou +
{
for(int j = 0;j<tab[i][1];j++)
{
if(n==-1)
{
timespec_get( &now10, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now10.tv_sec ) );
printf("%s.%09ld msg 10 : verif cli %d rang %d etat %d\n",strNow,now10.tv_nsec,i,j,verif[i][j]);
}
if(verif[i][j]!=1) // on cherche les trames manquantes
{
timespec_get( &now11, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now11.tv_sec ) );
printf("%s.%09ld msg 11 : missing trame %d client %d \n",strNow,now11.tv_nsec,j,i);
message = j;
struct sockaddr_in var1;
var1 = tab_addr[i];
sendto(listenfd, &message, sizeof(int), 0,(struct sockaddr*)&var1, sizeof(var1)); //on réclame
}
}
}
}
}
if((raz[i]==1) && (p.tab_launch[i]==0)) // si le client est mort et que le thread de reconstruction s'est lancé
{ // manque la
//RAZ pour ce client car il ne répondra plus de toute façon
time1[i]=0;
raz[i]=0;
//tab_addr[i]=0; // a voir plus tard
tab[i][1]=100;
cpt_img_f[i]=0;
p.tab_launch[i]=1; // contre error: (-215:Assertion failed) !_img.empty() in function 'imwrite'
for (int j=0;j<100;j++)
verif[i][j]=0;
timespec_get( &now12, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now12.tv_sec ) );
printf("%s.%09ld msg 14 : RAZ client %d \n",strNow,now12.tv_nsec,i);
struct sockaddr_in var;
var = tab_addr[i];
int message = 1000;
sendto(listenfd, &message, sizeof(int), 0,(struct sockaddr*)&var, sizeof(var)); // on dis au client d'afficher rep et de mourir
timespec_get( &now13, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now13.tv_sec ) );
printf("%s.%09ld msg 15 : on a retourner la reponse finale %d au client %d \n",strNow,now13.tv_nsec,message,i);
}
}
}
close(listenfd);
return 0;
}
void* server(void* data1)
{
struct timespec now1,now2,now3,now4,now5;
char strNow[ BUFFER_SIZE ];
//recopiage de donnée
timespec_get( &now1, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now1.tv_sec ) );
printf("%s.%09ld msg bis : DEBUT THREAD",strNow,now1.tv_nsec);
Donnee* p2 = (Donnee*)data1;
int client = p2->client;
int longueur = p2->longueur;
int thread = p2->index;
int cpt_img = p2->cpt;
printf(" THREAD %d CLI %d IMG %d\n",thread,client,cpt_img);
p2->thread_check[thread] = 0; // le thread est bien lancer
//pthread_cond_broadcast( &cond_var);
p2->tab_launch[client]=0; // on peut RAZ
timespec_get( &now2, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now2.tv_sec ) );
printf("%s.%09ld msg bis : p2 tab launch %d cli %d \n",strNow,now2.tv_nsec,p2->tab_launch[client],client);
timespec_get( &now3, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now3.tv_sec ) );
printf("%s.%09ld msg bis : on est dans le thread %d client %d \n",strNow,now3.tv_nsec,thread,client);
//printf("reconstruction img %d \n",p2->cpt);
//Donnee* p = (Donnee*)malloc(sizeof(Donnee)); // g++
// printf("longueur %d id-cli %d\n",p2->longueur,p2->client);
int reconstruc[longueur];
for(int j = 0;j<longueur;j++)
{
reconstruc[j]=img_ino[client][j];
//printf("%d ",reconstruc[j]);
}
int x = sizeof(reconstruc)/sizeof(reconstruc[0]);
std::vector<uchar> dest(reconstruc,reconstruc+x);
cv::Mat dst = cv::imdecode(dest,1);
char msg[9];
timespec_get( &now4, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now4.tv_sec ) );
printf("%s.%09ld msg bis : on a reconstruit l'image %d client %d \n",strNow,now4.tv_nsec,cpt_img,client);
sprintf(msg,"dst%02d.jpg",cpt_img);
//try
//{
cv::imwrite(msg,dst);
//}
/* catch (cv::Exception& e)
{
printf("j'ai attrapé l'erreur thread %d client %d\n reconstruc : \n",thread,client);
for(int j = 0;j<longueur;j++)v
printf("%d ",reconstruc[j]);
printf("img ino : \n");
for (int j = 0;j<100000;j++)
img_ino[client][j];
printf("\n");
const char* err_msg = e.what();
std::cout << "exception caught: " << err_msg << std::endl;
}*/
// il ne faut pas raz pr eviter erreur de img empty
p2->tab[thread]=0; // on libère le thread
p2->cpt1--;
p2->reponse[client]=1000;
timespec_get( &now5, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now5.tv_sec ) );
printf("%s.%09ld msg bis : END OF THREAD %d CLI %d IMG %d \n",strNow,now5.tv_nsec,thread,client,cpt_img);
// pthread_exit(NULL);
}
le code du client :
// udp client driver program
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#define PORT 5000
#define MAXLINE 1000
//lisa
#include <stdlib.h>
#include <unistd.h>
#include <netdb.h>
#include <vector>
#include <iostream>
#include <ctime>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/videoio/videoio.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgcodecs/imgcodecs.hpp>
#define TAILLE_PACK 10000
#define N 4 // entête
#define BUFFER_SIZE 50
using namespace cv;
using namespace std;
//g++ -Wall -o cli2 cli2.cpp -lopencv_core -lopencv_highgui -lopencv_videoio -lopencv_imgcodecs
void my_delay(int i) ;
int main()
{
clock_t ti,tf;
float t_tot;
int buffer[N+TAILLE_PACK]; //data a transmettre
int sockfd;
struct sockaddr_in servaddr;
int nico = 0;
int mica=0;
struct timespec now1,now2,now3,now4,now5,now6,now7,now8,now9,now10;
char strNow[ BUFFER_SIZE ];
// clear servaddr
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
servaddr.sin_family = AF_INET;
// create datagram socket
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
printf("Could not create socket \n");
}
// connect to server
timespec_get( &now1, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now1.tv_sec ) );
if(connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
{
printf("\n Error : Connect Failed \n");
exit(0);
}
else printf("%s.%09ld Connecté !cli2 \n",strNow,now1.tv_nsec);
while (nico == 0)
{
//my_delay(1);
mica++;
if(mica == 500)
nico = 10;
//envoie d'une image
Mat src = imread("3.jpg", IMREAD_COLOR);
//creation de l'entête
buffer[0]=2; //id_cli
buffer[1]=0; //envoie length
buffer[2]=1; //zone de selec
//COMPRESSION OPENCV DE IMAGE DS UN VECTEUR 1o
std::vector<uchar> buf;
imencode(".jpg",src,buf); // on envoie l'image compresser dans buf
//affichage des matrices
//for(int i=0;i<buf.size();i++)
// printf("%d \n",buf[i]);
int length = buf.size();
int inter[length]; // pour eviter les pb de caractères
std::copy(buf.begin(),buf.end(),inter);
/*for(int i=0;i<buf.size();i++)
printf("%d ",inter[i]);*/
buffer[3]=length; // on ajoute à l'entête la length
//TRAME DE DEBUT
timespec_get( &now2, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now2.tv_sec ) );
printf("%s.%09ld Envoie de la taille cli2! \n",strNow,now2.tv_nsec);
// request to send datagram no need to specify server address in sendto connect stores the peers IP and port
int end1 =1;
int recep1;
struct timeval timeout={0,500}; // quand 2 clients arrivent successivement
setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(struct timeval)); // recvfrom non bloquant après 2 secondes
while (end1 ==1) //tq j'ai pas reçu une reponse du serveur
{
sendto(sockfd,(int *) buffer,N+TAILLE_PACK,MSG_CONFIRM, (struct sockaddr*)&servaddr, sizeof(servaddr));
recvfrom(sockfd, &recep1, sizeof(int), 0, (struct sockaddr*)NULL, NULL);
if(recep1 == 300)
end1 = 2;
}
timespec_get( &now3, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now3.tv_sec ) );
printf("%s.%09ld trame de start envoyer, passons à la suite cli2!\n",strNow,now3.tv_nsec);
timeout={0,0}; // quand 2 clients arrivent successivement
setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(struct timeval)); // recvfrom redevient bloquant après cette étape
//printf("a = %d \n",a);
//MTN envoie data
buffer[1]=1;
//envoie par frame de 10 000 bits
timespec_get( &now4, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now4.tv_sec ) );
printf("%s.%09ld Envoie de l'image compressée cli2! \n",strNow,now4.tv_nsec);
int message_index = 0;
int r = length % TAILLE_PACK;
int num_message = (length-r)/TAILLE_PACK; //=7 70000/10000
int cpt=0;
ti = clock();
while(message_index < num_message)
{
timespec_get( &now5, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now5.tv_sec ) );
printf("%s.%09ld index %d cli2\n",strNow,now5.tv_nsec,message_index);
//prepare data
buffer[3]=message_index;
memcpy(&buffer[4],&inter[cpt],TAILLE_PACK*sizeof(int)); // on met les data //ça se passe pas bien
//visiblement c'est ici que le printf est important
//for(int i=4;i<TAILLE_PACK+4;i++) // afficher matrice
// printf("%d ",buffer[i]);
//printf("\n");
sendto(sockfd,(int *) buffer,(N+TAILLE_PACK)*sizeof(int),MSG_CONFIRM, (struct sockaddr*)&servaddr, sizeof(servaddr));
message_index++;
cpt+=TAILLE_PACK;
}
//TRAME DE FIN
buffer[3]=message_index;
timespec_get( &now6, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now6.tv_sec ) );
printf("%s.%09ld index %d cli2\n",strNow,now6.tv_nsec,message_index); // = 7
memcpy(&buffer[4],&inter[length-r],r*sizeof(int));
//for(int i=4;i<r+4;i++)
// printf("%d ",buffer[i]);
//printf("\n");
//attention après r on envoie du bulshit
sendto(sockfd,(int *) buffer,(N+TAILLE_PACK)*sizeof(int),MSG_CONFIRM, (struct sockaddr*)&servaddr, sizeof(servaddr));
tf = clock();
t_tot = (tf-ti);
//printf("t_tot %f \n t_tot %f s\n",t_tot,t_tot*1e-6);
//printf("c = %d\n",c);
int end = 0;
socklen_t len;
len=sizeof(servaddr);
int recep;
//boucle pour renvoyer les trames
while (end == 0)
{
timespec_get( &now7, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now7.tv_sec ) );
printf("%s.%09ld j'attend un msg du serveur cli2\n",strNow,now7.tv_nsec);
recvfrom(sockfd, &recep, sizeof(int), 0, (struct sockaddr*)NULL, NULL);
timespec_get( &now8, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now8.tv_sec ) );
printf("%s.%09ld je dois envoyer la trame %d cli2\n",strNow,now8.tv_nsec,recep);
if(recep != 100)
{
buffer[3]=recep;
if(recep == num_message) // si c'est la trame de fin
{
memcpy(&buffer[4],&inter[length-r],r*sizeof(int));
//for(int i = 4;i<r+4;i++)
// printf("%d ",buffer[i]);
}
else
{
memcpy(&buffer[4],&inter[recep*TAILLE_PACK],TAILLE_PACK*sizeof(int));
//for(int i = 4;i<TAILLE_PACK+4;i++)
// printf("%d ",buffer[i]);
}
sendto(sockfd,(int *) buffer,(N+TAILLE_PACK)*sizeof(int),MSG_CONFIRM, (struct sockaddr*)&servaddr, sizeof(servaddr));
}
if (recep == 100)
end = 1;
}
int end3 = 0;
//timeout={0,500}; // quand 2 clients arrivent successivement
//setsockopt(sockfd,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(struct timeval));
while(end3 ==0)
{
//on attend la reponse du serveur
timespec_get( &now9, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now9.tv_sec ) );
printf("%s.%09ld j'attend la reponse du serveur cli2 \n",strNow,now9.tv_nsec);
recvfrom(sockfd, &recep, sizeof(int), 0, (struct sockaddr*)NULL, NULL);
if(recep == 1000)
end3 = 1;
}
timespec_get( &now10, TIME_UTC );
strftime( strNow, BUFFER_SIZE, "%D %T", gmtime( &now10.tv_sec ) );
printf("%s.%09ld adieu cli2! \n",strNow,now10.tv_nsec);
// close the descriptor
}
close(sockfd);
}
//recvfrom(sockfd, &buffer, sizeof(int), 0, (struct sockaddr*)NULL, NULL);
/* socklen_t len;
len=sizeof(servaddr
*/
void my_delay(int i) /*Pause l'application pour i seconds*/
{
clock_t start,end;
start=clock();
while(((end=clock())-start)<=i*CLOCKS_PER_SEC);
}
j'ai le même code pour un deuxième client qui charge une image différente et un id différent. De manière aléatoire, dans les logs se passe la chose suivante :
le thread 0 est lancé mais rien n'est print de ce qui provient de se thread. Dans la suite du programme ce thread étant bloqué les reconstructions appellent uniquement les threads 1,2,3,4.
Un fonctionnement normal, on obtient les logs suivant :
05/05/22 12:41:24.222192553 msg 11 : missing trame 6 client 2 05/05/22 12:41:24.222195758 msg 11 : missing trame 7 client 2 05/05/22 12:41:24.222199112 msg 5 : Reconstruction classique 05/05/22 12:41:24.222228912 msg 6 : le client 3 a lancer le thread 0 05/05/22 12:41:24.222237805 msg bis : DEBUT THREAD THREAD 0 CLI 3 IMG 115 05/05/22 12:41:24.222255027 msg bis : p2 tab launch 0 cli 3 05/05/22 12:41:24.222247180 msg 2 : index 5 client 2 05/05/22 12:41:24.222259243 msg 3 : CLI 3 raz 1 cpt_img_f 0 05/05/22 12:41:24.222263698 msg 4 : CLI 2 raz 0 cpt_img_f 6 05/05/22 12:41:24.222265395 msg 14 : RAZ client 3 05/05/22 12:41:24.222256331 msg bis : on est dans le thread 0 client 3 05/05/22 12:41:24.222274193 msg 15 : on a retourner la reponse finale 1000 au client 3 05/05/22 12:41:24.222279489 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.222280454 msg 4 : CLI 2 raz 0 cpt_img_f 6 05/05/22 12:41:24.222281367 msg 7 : ON REGARDE CLI QUI N'ONT PAS PARLER DEPUIS LONGTEMPS 05/05/22 12:41:24.222282157 msg 8 : tf 500270; ti 500215; diff 55 05/05/22 12:41:24.222283139 msg 9 : cpt 6 tab 8 cli 2 05/05/22 12:41:24.222284212 msg 11 : missing trame 6 client 2 05/05/22 12:41:24.222289079 msg 11 : missing trame 7 client 2 05/05/22 12:41:24.222296539 msg 2 : index 6 client 2 05/05/22 12:41:24.222299077 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.222299975 msg 4 : CLI 2 raz 0 cpt_img_f 7 05/05/22 12:41:24.222304613 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.222305625 msg 4 : CLI 2 raz 0 cpt_img_f 7 05/05/22 12:41:24.222306593 msg 7 : ON REGARDE CLI QUI N'ONT PAS PARLER DEPUIS LONGTEMPS 05/05/22 12:41:24.222307347 msg 8 : tf 500296; ti 500291; diff 5 05/05/22 12:41:24.222308424 msg 9 : cpt 7 tab 8 cli 2 05/05/22 12:41:24.222309488 msg 11 : missing trame 7 client 2 05/05/22 12:41:24.222318221 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.222319248 msg 4 : CLI 2 raz 0 cpt_img_f 7 05/05/22 12:41:24.222320176 msg 7 : ON REGARDE CLI QUI N'ONT PAS PARLER DEPUIS LONGTEMPS 05/05/22 12:41:24.222320820 msg 8 : tf 500309; ti 500291; diff 18 05/05/22 12:41:24.222321845 msg 9 : cpt 7 tab 8 cli 2 05/05/22 12:41:24.222322894 msg 11 : missing trame 7 client 2 05/05/22 12:41:24.222330958 msg 2 : index 6 client 2 05/05/22 12:41:24.222332868 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.222333772 msg 4 : CLI 2 raz 0 cpt_img_f 7 05/05/22 12:41:24.222338221 msg 2 : index 7 client 2 05/05/22 12:41:24.222339789 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.222340662 msg 4 : CLI 2 raz 0 cpt_img_f 8 05/05/22 12:41:24.222341533 msg 5 : Reconstruction classique 05/05/22 12:41:24.222366966 msg 6 : le client 2 a lancer le thread 1 05/05/22 12:41:24.222369870 msg bis : DEBUT THREAD THREAD 1 CLI 2 IMG 116 05/05/22 12:41:24.222372247 msg 2 : index 7 client 2 05/05/22 12:41:24.222374704 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.222375624 msg 4 : CLI 2 raz 1 cpt_img_f 0 05/05/22 12:41:24.222377760 msg 14 : RAZ client 2 05/05/22 12:41:24.222372455 msg bis : p2 tab launch 0 cli 2 05/05/22 12:41:24.222380629 msg bis : on est dans le thread 1 client 2 05/05/22 12:41:24.222382793 msg 15 : on a retourner la reponse finale 1000 au client 2 05/05/22 12:41:24.222387185 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.222388004 msg 4 : CLI 2 raz 0 cpt_img_f 0 05/05/22 12:41:24.224900699 msg bis : on a reconstruit l'image 115 client 3 05/05/22 12:41:24.225475718 msg bis : on a reconstruit l'image 116 client 2 05/05/22 12:41:24.226909972 msg 1 : ON A RECU TRAME DE START
05/05/22 12:41:24.226913755 msg 3 : CLI 3 raz 0 cpt_img_f 0 05/05/22 12:41:24.226915189 msg 4 : CLI 2 raz 0 cpt_img_f 0 05/05/22 12:41:24.226985191 msg 2 : index 0 client 3 05/05/22 12:41:24.226989791 msg 3 : CLI 3 raz 0 cpt_img_f 1 05/05/22 12:41:24.226991090 msg 4 : CLI 2 raz 0 cpt_img_f 0 05/05/22 12:41:24.226995305 msg 2 : index 1 client 3 05/05/22 12:41:24.226997614 msg 3 : CLI 3 raz 0 cpt_img_f 2 05/05/22 12:41:24.226998483 msg 4 : CLI 2 raz 0 cpt_img_f 0 05/05/22 12:41:24.227001920 msg 2 : index 2 client 3 05/05/22 12:41:24.227004111 msg 3 : CLI 3 raz 0 cpt_img_f 3 05/05/22 12:41:24.227004921 msg 4 : CLI 2 raz 0 cpt_img_f 0 05/05/22 12:41:24.227008237 msg 2 : index 3 client 3 05/05/22 12:41:24.227010410 msg 3 : CLI 3 raz 0 cpt_img_f 4 05/05/22 12:41:24.227011202 msg 4 : CLI 2 raz 0 cpt_img_f 0 05/05/22 12:41:24.227014826 msg 2 : index 4 client 3 05/05/22 12:41:24.227031039 msg 3 : CLI 3 raz 0 cpt_img_f 5 05/05/22 12:41:24.227031953 msg 4 : CLI 2 raz 0 cpt_img_f 0 05/05/22 12:41:24.227035709 msg 2 : index 5 client 3 05/05/22 12:41:24.227037952 msg 3 : CLI 3 raz 0 cpt_img_f 6 05/05/22 12:41:24.227038786 msg 4 : CLI 2 raz 0 cpt_img_f 0 05/05/22 12:41:24.227176220 msg bis : END OF THREAD 0 CLI 3 IMG 115
Comment est-ce possible que je n'ai pas d'erreur à la création du thread mais que pourtant il se passe rien ?
Pas sur que tu auras beaucoup d'aide avec un code comme. Plus personne (de sérieux) ne code comme ça depuis 20 ans. Et ceux qui savent coder comme ça savent à quel point c'est galère et n'entrent pas dans ce type de code sauf très bonne raison.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Discord NaN. Mon site.