problème taille de buffer /socket

problème taille de buffer /socket - C++ - Programmation

Marsh Posté le 26-02-2003 à 19:33:34    

bonjour,
Je voudrait faire un programme qui fait un genre de tunnel, pour rediriger les connexions entrantes sur le port XX vers le port port YY de la machine A.B.C.D  
 
g taper le code suivant

Code :
  1. #ifdef unix
  2. #define closesocket close
  3. #include <sys/types.h>
  4. #include <sys/socket.h>
  5. #include <netinet/in.h>
  6. #include <arpa/inet.h>
  7. #include <netdb.h>
  8. #else
  9. #define WIN32
  10. #include <windows.h>
  11. #include <winsock.h>
  12. #endif
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <iostream.h>
  16. #define WEBPORT 2000
  17. #define LOCALPORT 80
  18. #define BUFFER 100000
  19. #define QLEN 6
  20. int visits = 0;
  21. extern int errno;
  22. char localhost[] = "192.168.0.81";
  23. int sizeString(char buf[BUFFER]);
  24. int main ()
  25. {
  26. struct hostent *ptrh_cli;
  27. struct protoent *ptr_serveur,*ptrp_client;
  28. struct sockaddr_in serveur,sad_cli,sad_serv;
  29. int port_cli,sd_cli,n_cli,alen,port,sd,sd2,n,i = 0;;
  30. char *host_cli;
  31. char buffer[BUFFER],buf_cli[BUFFER];
  32. while (i < BUFFER)
  33. {
  34.  buffer[i] = '*';
  35.  buffer2[i] = '*';
  36.  buf_cli[i] = '*';
  37.  i++;
  38. }
  39. #ifdef WIN32
  40. WSADATA wsaData;
  41. WSAStartup(0x0101 , &wsaData);
  42. #endif
  43. memset((char *)&sad_serv,0,sizeof(sad_serv));
  44. sad_serv.sin_family = AF_INET;
  45. sad_serv.sin_addr.s_addr = INADDR_ANY;
  46. port = WEBPORT;
  47. sad_serv.sin_port = htons((u_short) port);
  48. if (((int)(ptr_serveur = getprotobyname("tcp" ))) ==0)
  49. {
  50.  cerr<<"failed to get prtocol by name"<<endl;
  51.  exit(1);
  52. }
  53. sd = socket(PF_INET, SOCK_STREAM , ptr_serveur->p_proto);
  54. if (sd < 0)
  55. {
  56.  cerr<<"erreur while initializing socket"<<endl;
  57.  exit(1);
  58. }
  59. if (bind(sd,(struct sockaddr *)&sad_serv, sizeof(sad_serv))<0)
  60. {
  61.  cerr<<"error while binding socket"<<endl;
  62.  exit(1);
  63. }
  64. if (listen(sd ,QLEN) >= 0)
  65. {
  66.  cout<<"Listening port "<<port<<"..."<<endl;
  67. }
  68. else
  69. {
  70.  cerr<<"failed to listen port "<<port<<" ..."<<endl;
  71.  exit(1);
  72. }
  73. memset((char *) &sad_cli,0,sizeof(sad_cli));
  74. sad_cli.sin_family = AF_INET;
  75. port_cli = LOCALPORT;
  76. sad_cli.sin_port = htons ((u_short)port_cli);
  77. host_cli = localhost;
  78. ptrh_cli = gethostbyname(host_cli);
  79. if (((char *)ptrh_cli) == NULL)
  80. {
  81.  cerr<<"host unknown"<<host_cli<<endl;
  82.  exit(1);
  83. }else
  84. {
  85.  cout<<"attempting to reach "<<(char *)ptrh_cli->h_name<<" ..."<<endl;
  86. }
  87. memcpy(&sad_cli.sin_addr , ptrh_cli->h_addr,ptrh_cli->h_length);
  88. if (((int)(ptrp_client = getprotobyname("tcp" ))) == 0)
  89. {
  90.  cerr<<"failed to get prtocol by name"<<endl;
  91.  exit(1);
  92. }
  93. //listen(sd,QLEN);
  94. while(true)
  95. {
  96.  alen = sizeof(serveur);
  97.  if ((sd2=accept(sd,(struct sockaddr *)&serveur ,&alen))<0)
  98.  {
  99.   cerr<<"unable to accept remote user\n"<<endl;
  100.   exit(1);
  101.  }else
  102.  {
  103.   visits++;
  104.   cout<<endl<<"connection id: "<<visits<<endl;
  105.  }
  106.  sd_cli = socket(PF_INET, SOCK_STREAM, ptrp_client->p_proto);
  107.  if(sd_cli < 0)
  108.  {
  109.   cerr<<"erreur while initializing socket"<<endl;
  110.   exit(1);
  111.  }
  112.  if (connect(sd_cli,(struct sockaddr *)& sad_cli,sizeof(sad_cli)) >= 0)
  113.  {
  114.   cout<<"*** connected to "<<localhost<<" ***"<<endl;
  115.  }else
  116.  {
  117.   cerr<<"attempt to connect "<<localhost<<" failed ... aborting"<<endl;
  118.   exit(1);
  119.  }
  120.  n = recv(sd2,buffer,sizeof(buffer),0);
  121.  send (sd_cli,buffer,strlen(buffer),0);
  122.  n_cli = recv(sd_cli,buf_cli,sizeof(buf_cli),0);
  123.  send (sd2,buf_cli,sizeString(buf_cli)-1,0);
  124.  closesocket(sd_cli);
  125.  closesocket(sd2);
  126. }
  127. return 0;
  128. }
  129. int sizeString(char buf[BUFFER])
  130. {
  131. int i = 0;
  132. bool b = true;
  133. while (i < BUFFER && b == true)
  134. {
  135.  int j = i,c=0;
  136.  while (j<i+15)
  137.  {
  138.   if(buf[j] == '*')
  139.    c++;
  140.   j++;
  141.  }
  142.  if (c >= 14)
  143.   b = false;
  144.  i++;
  145. }
  146. return i;
  147. }


 
a priori ca fonctionne mais lorsque que j'essaye de transferer un buffer suprérieur a 10220 bytes ca foire  :(  
Je vois pas trop comment m'y prendre ...si vous pouvez me guider sur le principe pour gerer les transferts en paquets...
Merci d'avance  :jap:

Reply

Marsh Posté le 26-02-2003 à 19:33:34   

Reply

Marsh Posté le 26-02-2003 à 21:44:02    

Euh il aime peut-etre pas les variables globales trop grosses ?
Decris exactement ce qui se passe... Utilise un debugger...

Reply

Marsh Posté le 26-02-2003 à 22:05:44    

Ben concrètement je teste le prog avec un serveur web sur la machine A.B.C.D , et si la page (ou image) est supérieur a 10ko elle s'affiche pas ou mal dans le navigateur, alors que je crée un buffer de 100ko pour stocker les données transferées.
Lorsque j'affiche la taille du buffer en cours elle vaut tj 10220 maximum (ou moins lorsque chaque objet de la page est < 10ko)

Reply

Marsh Posté le 27-02-2003 à 15:30:38    

un bon vieux up  :bounce:

Reply

Marsh Posté le 27-02-2003 à 15:38:23    

un buffer de 100000 octets ... :pt1cable:  
vous etes les meilleurs!
Petite question: pourquoi un buffer aussi gros? 2048 est une taille raisonnable ...

Reply

Marsh Posté le 27-02-2003 à 15:57:37    

ben c présicément mon prob...
d'abord je n arrive pas remplir les 100000 bytes du buffer,
Et ensuite c justement ske je voulais savoir comment gerer des transfert de gros fichiers en ptit paquet avec un ptit buffer.

Reply

Marsh Posté le 27-02-2003 à 16:25:13    

les paquets TCP ou UDP a une taille maximal qui n'est pas très grande ... tout est découpé en morceaux et reassemblé par le destinataire donc un gros buffer n'a pas d'intérêt ...
Comment lire un gros fichier? Comme les petits:  
 

Code :
  1. FILE * peripherique = fopen(fichier_in, "r" );
  2.   if(peripherique == NULL)
  3.     {
  4. //on arrete tout!
  5.     }
  6.   FILE * fichier_iso = fopen(fichier_out, "w" );
  7.   if(fichier_iso == NULL)
  8.     {
  9.          fclose(peripherique);
  10. //on arrete tout!
  11.     }
  12.   int taille_lu = 1;
  13.   while(taille_lu >= 0)
  14.     {
  15.       taille_lu = read(fileno(peripherique), buffer, taille);
  16.       progression = progression + ((double)taille_lu * 100)/(double)taille_cd;
  17.       printf("progression = '%f'\n", progression);
  18.       if(taille_lu == 0)
  19.         {
  20.           //fini
  21.           resultat = 0;
  22.           break;
  23.         }
  24.       if(taille_lu < 0)
  25.         {
  26.           //un error a eu lieu!
  27.           fprintf(stderr, "L'erreur '%s' a eu lieu pendant l'extraction du iso\n", strerror(errno));
  28.           unlink(nom_iso.val());
  29.           progression=0.0;
  30.           break;
  31.         }
  32.       write(fileno(fichier_iso), buffer, taille_lu);
  33.     }
  34.   fclose(fichier_iso);
  35.   fclose(peripherique);

 
Cet extrait de code permet de copier un fichier de taille quelconque ... il suffit que tu remplace fichier_iso par ta socket!
 
EDIT: pas terrible, la rendue ...


Message édité par western le 27-02-2003 à 16:26:10
Reply

Marsh Posté le 27-02-2003 à 16:50:42    

merci  :jap:  
J'en ai pour l'aprem avec ca , mais tant mieux y fait bo , (et moi j aime la pluie  :D )
Je voudrait juste etre sur d'avoir compris la méthode,
Donc peripherique c le fichier qui contient ce que je veux transferer?
Et lorsque tu fait write fichier_iso je doit faire un send ?
ca bien ca?
Et est que la méthode peut s appliquer pour recevoir un fichier (en inversant les fonctions)?
Encore merci pour ton aide  :)

Reply

Marsh Posté le 27-02-2003 à 17:06:26    

bingo! cela doit être ça! (cela fait au moins deux ans que j'ai pas touché aux sockets en C)

Reply

Marsh Posté le 27-02-2003 à 17:17:28    

oki nikel  ,encore merci  :jap:  
une dernière question ( je pousse la  :D )
Vous me conseillez quoi comme sentinelle mieux 15 '*'.
Le char 4 (EOT) sert a ca ?

Reply

Marsh Posté le 27-02-2003 à 17:17:28   

Reply

Marsh Posté le 27-02-2003 à 19:40:11    

heu voila je vien de taper ca

Code :
  1. #ifndef unix
  2. #define WIN32
  3. #include <windows.h>
  4. #include <winsock.h>
  5. #else
  6. #define closesocket close
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <netdb.h>
  11. #endif
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <iostream.h>
  15. #include <fstream.h>
  16. #define PROTOPORT 2000
  17. #define QLEN 6
  18. #define SIZEOFBUFFER 5000
  19. int visits = 0;
  20. char * filename ="d:/mod/test/Debug/q3iscr.jpg";
  21. void main ()
  22. {
  23. int i = 0;
  24. int size=0;int j = 0;
  25. struct hostent *ptrh;
  26. struct protoent *ptrp;
  27. struct sockaddr_in cad;
  28. struct sockaddr_in sad;
  29. int sd,sd2;
  30. int port;
  31. int alen;
  32. int n;
  33. char buffer[SIZEOFBUFFER];
  34. #ifdef WIN32
  35. WSADATA wsaData;
  36. WSAStartup(0x0101 , &wsaData);
  37. #endif
  38. memset((char *)&sad,0,sizeof(sad));
  39. sad.sin_family = AF_INET;
  40. sad.sin_addr.s_addr = INADDR_ANY;
  41. port = PROTOPORT;
  42. if (port > 0)
  43. sad.sin_port = htons((u_short) port);
  44. else
  45. {
  46.  fprintf(stderr,"numero de port invalide" );
  47.  exit(1);
  48. }
  49. if (((int)(ptrp = getprotobyname("tcp" ))) ==0)
  50. {
  51.  fprintf (stderr,"conversion de \"tcp\" impossible" );
  52.  exit(1);
  53. }
  54. sd = socket(PF_INET, SOCK_STREAM , ptrp->p_proto);
  55. if (sd < 0)
  56. {
  57.  fprintf(stderr,"erreur (socket)\n" );
  58.  exit(1);
  59. }
  60. if (bind(sd,(struct sockaddr *)&sad, sizeof(sad))<0)
  61. {
  62.  fprintf(stderr,"erreur (bind)\n" );
  63.  exit(1);
  64. }
  65. if (listen(sd ,QLEN < 0))
  66. {
  67.  fprintf(stderr,"erreur (listen)\n" );
  68.  exit(1);
  69. }
  70. cout<<"Listening port "<<port<<"..."<<endl;
  71. while (1)
  72. {
  73.  alen = sizeof(cad);
  74.  if ((sd2=accept(sd,(struct sockaddr *)&cad ,&alen))<0)
  75.  {
  76.   fprintf(stderr,"accept failed\n" );
  77.   exit(1);
  78.  }else
  79.  {
  80.   cout<<endl<<"conection id: "<<visits<<endl;
  81.  }
  82.  visits++;
  83.  ifstream file (filename, ios::in|ios::binary|ios::ate);
  84.  size = file.tellg();
  85.  file.seekg (0, ios::beg);
  86.  i = 0;
  87.  while(j < size/SIZEOFBUFFER)
  88.  {
  89.   j++;
  90.  }
  91.  int lastbuf = size - (j*SIZEOFBUFFER);
  92.  while(i <= size/SIZEOFBUFFER)
  93.  {
  94.   file.read(buffer, SIZEOFBUFFER);
  95.   cout<<"lecture buffer:"<<i<<endl;
  96.   if(i == j )
  97.   {
  98.    send (sd2,buffer,lastbuf,0);
  99.    cout<<lastbuf<<" bytes sended"<<endl;
  100.   }else
  101.   {
  102.    send (sd2,buffer,SIZEOFBUFFER,0);
  103.    cout<<SIZEOFBUFFER<<" bytes sended"<<endl;
  104.   }
  105.   i++;
  106.  }
  107.  file.close();
  108.  cout<<endl<<"******************************"<<endl;
  109.  closesocket(sd2);
  110. }
  111. }


La y as plus qu'un socket , c juste pour tester.
La ca marche , en fait je peut transferer par exemple une image (qui pour l'instant est sur le disque local),
Mais le prob dans ie elle s'affiche très bien mais sous d'autre nav comme mozilla ou konqueror ca foire.
Qd ca sera le contenu renvoyer par le apache de l'autre machine (qd j aurais mis l'autre socket) ca marchera la?

Reply

Marsh Posté le 27-02-2003 à 23:57:13    

bon voila g capter comment ca marchait ,c t pas nécessaire d'utiliser un fichier en fait , mais c qd meme ca qui ma mis sur la voie   ;)  
Et les deux problèmes ci dessus se sont bien résolu d eux meme comme j esperait  :)  
c t tout con en fait...

Code :
  1. #ifndef unix
  2. #define WIN32
  3. #include <windows.h>
  4. #include <winsock.h>
  5. #else
  6. #define closesocket close
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <netinet/in.h>
  10. #include <netdb.h>
  11. #endif
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <iostream.h>
  15. #include <fstream.h>
  16. #define SIZEOFBUFFER 2000
  17. #define WEBPORT 2000
  18. #define LOCALPORT 80
  19. #define QLEN 6
  20. extern int errno;
  21. char localhost[] = "192.168.0.81";
  22. char * filename ="d:/mod/test/Debug/tmp.dat";
  23. int visits = 0;
  24. void main ()
  25. {
  26. ofstream file (filename, ios::in|ios::binary|ios::ate);
  27. int size=0;int j = 0;
  28. struct hostent *ptrh_cli;
  29. struct protoent *ptr_serveur,*ptrp_client;
  30. struct sockaddr_in serveur,sad_cli,sad_serv;
  31. int port_cli,sd_cli,n_cli,alen,port,sd,sd2,n,i = 0;
  32. char buffer[SIZEOFBUFFER],buf_cli[SIZEOFBUFFER];
  33. char *host_cli;
  34. while (i < SIZEOFBUFFER)
  35. {
  36.  buffer[i] = '*';
  37.  buf_cli[i] = '*';
  38.  i++;
  39. }
  40. #ifdef WIN32
  41. WSADATA wsaData;
  42. WSAStartup(0x0101 , &wsaData);
  43. #endif
  44. memset((char *)&sad_serv,0,sizeof(sad_serv));
  45. sad_serv.sin_family = AF_INET;
  46. sad_serv.sin_addr.s_addr = INADDR_ANY;
  47. port = WEBPORT;
  48. sad_serv.sin_port = htons((u_short) port);
  49. if (((int)(ptr_serveur = getprotobyname("tcp" ))) ==0)
  50. {
  51.  cerr<<"failed to get prtocol by name"<<endl;
  52.  exit(1);
  53. }
  54. sd = socket(PF_INET, SOCK_STREAM , ptr_serveur->p_proto);
  55. if (sd < 0)
  56. {
  57.  cerr<<"erreur while initializing socket"<<endl;
  58.  exit(1);
  59. }
  60. if (bind(sd,(struct sockaddr *)&sad_serv, sizeof(sad_serv))<0)
  61. {
  62.  cerr<<"error while binding socket"<<endl;
  63.  exit(1);
  64. }
  65. if (listen(sd ,QLEN) >= 0)
  66. {
  67.  cout<<"Listening port "<<port<<"..."<<endl;
  68. }
  69. else
  70. {
  71.  cerr<<"failed to listen port "<<port<<" ..."<<endl;
  72.  exit(1);
  73. }
  74. memset((char *) &sad_cli,0,sizeof(sad_cli));
  75. sad_cli.sin_family = AF_INET;
  76. port_cli = LOCALPORT;
  77. sad_cli.sin_port = htons ((u_short)port_cli);
  78. host_cli = localhost;
  79. ptrh_cli = gethostbyname(host_cli);
  80. if (((char *)ptrh_cli) == NULL)
  81. {
  82.  cerr<<"host unknown"<<host_cli<<endl;
  83.  exit(1);
  84. }else
  85. {
  86.  cout<<"attempting to reach "<<(char *)ptrh_cli->h_name<<" ..."<<endl;
  87. }
  88. memcpy(&sad_cli.sin_addr , ptrh_cli->h_addr,ptrh_cli->h_length);
  89. if (((int)(ptrp_client = getprotobyname("tcp" ))) == 0)
  90. {
  91.  cerr<<"failed to get prtocol by name"<<endl;
  92.  exit(1);
  93. }
  94. //listen(sd,QLEN);
  95. while (1)
  96. {
  97.  alen = sizeof(serveur);
  98.  if ((sd2=accept(sd,(struct sockaddr *)&serveur ,&alen))<0)
  99.  {
  100.   fprintf(stderr,"accept failed\n" );
  101.   exit(1);
  102.  }else
  103.  {
  104.   cout<<endl<<"conection id: "<<visits<<endl;
  105.  }
  106.  visits++;
  107.  i = 0;
  108.  sd_cli = socket(PF_INET, SOCK_STREAM, ptrp_client->p_proto);
  109.  if(sd_cli < 0)
  110.  {
  111.   cerr<<"erreur while initializing socket"<<endl;
  112.   exit(1);
  113.  }
  114.  if (connect(sd_cli,(struct sockaddr *)& sad_cli,sizeof(sad_cli)) >= 0)
  115.  {
  116.   cout<<"*** connected to "<<localhost<<" ***"<<endl;
  117.  }else
  118.  {
  119.   cerr<<"attempt to connect "<<localhost<<" failed ... aborting"<<endl;
  120.   exit(1);
  121.  }
  122.  n = recv(sd2,buffer,sizeof(buffer),0);
  123.  send (sd_cli,buffer,n,0);
  124.     n_cli=5000;
  125.  while (n_cli != 0 && n_cli != -1)//c t juste cette boucle ki fallait faire
  126.  {
  127.   n_cli = recv(sd_cli,buf_cli,sizeof(buf_cli),0);
  128.   //file.write(buf_cli,n_cli);
  129.   if (n_cli != 0)
  130.   send (sd2,buf_cli,n_cli,0);
  131.   cout<<n_cli<<"bytes transfered"<<endl;
  132.  }
  133.  closesocket(sd_cli);
  134.         //file.close();
  135.  cout<<endl<<"******************************"<<endl;
  136. }
  137.         closesocket(sd2);
  138. }


Mais y reste encore un prob c que c très (trop) lent...
Entre chaque requete transmise puis retransmise y as des long moment ou y fout rien ...Et je vois pas ou est le prob  :(  
Si par exemple j'arriverait a faire le meme algo mais en me connectant qu'une seule fois a l autre machine (192.168.0.81)  
j'y gagnerait bcp?
Si qqn peut encore m'aider ca serait super   :jap:


Message édité par Nico5779 le 27-02-2003 à 23:59:19
Reply

Marsh Posté le 28-02-2003 à 09:31:54    

Amigo, soit tu fais du C (memcpy) soit du C++(cout) ... Il ne faut pas melanger les choses car cela est une très mauvaise pratique (pas de troll, svp)
Pour tes problèmes, plutard peut-être car là
1) je ne suis pas reveillé (une mauvaise nuit);
2) j'ai très mal à la gorge, à la tête (une mauvaise nuit) et pour courronner le tout un nez qui n'arrete pas de couler ...

Reply

Marsh Posté le 28-02-2003 à 21:03:31    

je suis d'accord avec toi en ce qui concerne les normes , mais c le genre de detail que je regle qd ca marche.
Or la ...  :sweat:  
Sinon jte souhaite un bon retablissement  :)  
Les autres, si vous avez des remarques qui pourrait m'aider ne vous genez pas  :)

Reply

Marsh Posté le 02-03-2003 à 18:36:18    

bon je crois que j'ai trouver ,le prob venait quand y recevait le dernier paquet de taille zero,
Mais g encore des probs  :(  
Je voulait utiliser le flag MSG_EOR
Mais visual me sort qu'il le connait pas.
 
edit: le prob avec gcc est resolu mais pas l'autre...
redit: nan en fait c MSG_WAITALL le bon flag mais c pareil visual me sort tj qu'il le connait pas... :/


Message édité par Nico5779 le 02-03-2003 à 18:51:10
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed