Aller au contenu

[C/C++][Resolu]Socket,server


Messages recommandés

Bon voila je débute en c++ et plus précisément dans les sockets, alors j'aurait aimer faire un server qui ce contente d'analyser tout les messages qu'on lui envoi et de répondre à certaine commande tel que le !salut, mais je n’y arrive pas... :D

Alors j'ai commencer ce code à l'aide d'un tutorial mais j'arrive pas à le faire répondre aux messages dans le genre !salut.

Et aussi si quelqu'un a une idée pourquoi il ne dit "Hello word" que quand on à envoyer le premier message et non quand on ce connect...

Voici le code :

#include <winsock2.h>      /*socket*/
#include <stdio.h>      	/*printf*/
#pragma comment(lib, "ws2_32.lib")

void main()
{
WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);

SOCKET sock;
SOCKET csock;
SOCKADDR_IN sin;
SOCKADDR_IN csin;
char buffer[BUFSIZ];;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family      = AF_INET;
sin.sin_port        = htons(4444);
sock = socket(AF_INET,SOCK_STREAM,0);
bind(sock, (SOCKADDR *)&sin, sizeof(sin));


listen(sock,0);


while(1) {

 memset(buffer, '\0', BUFSIZ); /*on vide le buffer*/
 recv(csock, buffer, BUFSIZ-1, 0);
 printf("%s",buffer);


 int sinsize = sizeof(csin);
 csock = accept(sock, (SOCKADDR *)&csin, &sinsize);

 if(csock != INVALID_SOCKET) {
 	send(csock, "Hello world!\r\n", 14, 0);
 }

 if(strstr(buffer,"!salut")) {
 	sprintf(buffer, "Commen ça va ?\n");
 	send(csock, buffer, sizeof(buffer), 0);
 }
 
}

}

Lien vers le commentaire
Partager sur d’autres sites

ca va faire un bail que j'en ai pas fait (7_8 mois) mais y'a un truc qui me chagrine

  csock = accept(sock, (SOCKADDR *)&csin, &sinsize);

tu accepte une socket mais tu la libère pas ?

edit : j'ai creer un prog client et serveur qui communique entre eux pour s'echanger des fichier acec des connections socket. ca t'interresse pour voir comme j'ai fait ?

edit 2 : moi j'accept pas des sockets. je me connecte a des sockets et je me deconnecter avec bind puis listen (pour le serveur)

le client utilise connect

mais quand j'y repense je fais ca en C et non en C++

Lien vers le commentaire
Partager sur d’autres sites

en fait, j'ai relu ton code et regarder le mien

moi j'ai une boucle infini qui tourne

si un client arrive, je lui attribut une socket, il se "connect" dessus

le serveur l' "accept" comme tu l'a fait

puis il discute

puis je ferme la socket de communication avec un close(socket)

donc un "close(csock)" dans ton cas

mais ce n'est qu'une formalité pour evité de futur plantage en cas de soket non supprimé

edit :

lors de la lecture moi je fais

read(descripteur de soket , buffer, taille a lire)

mais apparement ton erreur viens du fait que tu lit dabord les données et apres tu accept la socket.

ce devrait etre l'inverse je pense

while(1) {

memset(buffer, '\0', BUFSIZ); /*on vide le buffer*/

int sinsize = sizeof(csin);
csock = accept(sock, (SOCKADDR *)&csin, &sinsize);

if(csock != INVALID_SOCKET) {
 send(csock, "Hello world!\r\n", 14, 0);
}

recv(csock, buffer, BUFSIZ-1, 0);
printf("%s",buffer);

if(strstr(buffer,"!salut")) {
 sprintf(buffer, "Commen ça va ?\n");
 send(csock, buffer, sizeof(buffer), 0);
}

}

Lien vers le commentaire
Partager sur d’autres sites

OK OK je vais tester.

edit: Nan ça n'a rien changer. J'ai toujours les meme probleme :

Je lance mon serveur ensuite je fais connecter mon client dessus, la j'envoie un message au serveur, il affiche le message a l'écran me répond par "Hello world" ensuite sur le client je peut renvoyer un autre message mais il ne s'affiche plus sur le serveur. Et le serveur ne répond pas non plus lorsque j'envois "!salut".

Code du client :

#include <winsock2.h>      /*socket*/
#include <stdio.h>      	/*printf*/
#include <iostream>
#pragma comment(lib, "ws2_32.lib")

void main()
{

char ip[256];
std::cout << "IP : ";
std::cin >> ip;
std::cout << std::endl;

WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);

SOCKET sock;
SOCKADDR_IN sin;
char buffer[BUFSIZ];
char msg[256];

sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_family      = AF_INET;
sin.sin_port        = htons(4444);
sock = socket(AF_INET,SOCK_STREAM,0);
bind(sock, (SOCKADDR *)&sin, sizeof(sin));


connect(sock, (SOCKADDR *)&sin, sizeof(sin));


while(1) {

 std::cout << "MSG : ";
 std::cin >> msg;

 sprintf(buffer, "%s\n", msg);
 send(sock, buffer, sizeof(buffer), 0);


 memset(buffer, '\0', BUFSIZ); /*on vide le buffer*/
 recv(sock, buffer, BUFSIZ-1, 0);
 printf("%s",buffer);

} 


}/* fin du programme */

Lien vers le commentaire
Partager sur d’autres sites

Au passage j'ai rajouter un closesocket() a la fin de la boucle sur le serveur et maintenant je peut envoyer autant de commande que je veux sur le serveur mais ce dernier n'affiche que la première.

  while(1) {

 memset(buffer, '\0', BUFSIZ); /*on vide le buffer*/
 
 int sinsize = sizeof(csin);
 csock = accept(sock, (SOCKADDR *)&csin, &sinsize);

 if(csock != INVALID_SOCKET) {
 	send(csock, "Hello world!\r\n", 14, 0);
 }

 recv(csock, buffer, BUFSIZ-1, 0);
 printf("%s",buffer);

 if(strstr(buffer,"!salut")) {
 	sprintf(buffer, "Commen ça va ?\n");
 	send(csock, buffer, sizeof(buffer), 0);
 }

 closesocket(csock);
 
}

}

Lien vers le commentaire
Partager sur d’autres sites

c bon tu peux enlever ton adresse mail

je t'envoie ca dès que je peux

edit : mdr je viens de trouver

c'est toujours l'erreur conne qui est la plus dur

  if(csock != INVALID_SOCKET) {
 send(csock, "Hello world!\r\n", 14, 0);
}

si csock n'est pas une socket invalide

en francais : si csock est une bonne socket faire envoye hello world

donc si tu fait ca

  if(csock == INVALID_SOCKET) {
 send(csock, "Hello world!\r\n", 14, 0);
}

ca devrai fonctionner

et vire la fermeture de socket dans le while(1) du serveur

en fait dans ton cas ca sert a rien, faudrai le mettre apres le while(1) donc ca sert a rien de le mettre

Lien vers le commentaire
Partager sur d’autres sites

C'est bon en effet il répond bien au !salut.

Mais il reste une petit problème, quand j'envoit "!salut" il me repond bien par "Ca va ?".

Mais une fois qu'il ma répondu j'ai beau lui renvoyer "!salut" il ne repond plus...

Et puis ,

  if(csock == INVALID_SOCKET) {
send(csock, "Hello world!\r\n", 14, 0);
}

En gros il ne sert pas a grand chose alors autant le supprimer nan ?

edit: En effet ça sert à rien ça marche très bien sans. Mais j'ai toujours pas réussit a faire en sorte qui réponde toujours...

Lien vers le commentaire
Partager sur d’autres sites

le supprimer : c'est pas bien

en fait ca fais parti de la gestion des erreurs

si il y a un pb dans la connection des sockets, avec ce que tu a enlever, tu aura pu savoir que cela venais de la

parcontre

  if(csock == INVALID_SOCKET) {
send(csock, "Hello world!\r\n", 14, 0);
}

ca sert a rien

je decode en francais : si la socket n'est pas valide, envoyer hello world par la socket

archi null comme code d'erreur

je ferai plutot

  if(csock == INVALID_SOCKET) {
printf("erreur de connection socket");
}

pour l'autre pb, tu a bien enlever le

  closesocket(csock);

dans le server ?

edit : y'a un truc qui est bizarre : tu fait du C++ ou du C

car je vois que des fonctions C dans ton code

de plus les #include, incluse des fonctions C comme printf

Lien vers le commentaire
Partager sur d’autres sites

Oui si tu veux comme code j'ai ça pour le moment :

#include <winsock2.h>                        /*socket*/
#include <stdio.h>                            /*printf*/
#pragma comment(lib, "ws2_32.lib")

void main()
{
   WSADATA WSAData;
   WSAStartup(MAKEWORD(2,0), &WSAData);

   SOCKET sock;
   SOCKET csock;
   SOCKADDR_IN sin;
   SOCKADDR_IN csin;
   char buffer[BUFSIZ];;
   sin.sin_addr.s_addr = htonl(INADDR_ANY);
   sin.sin_family      = AF_INET;
   sin.sin_port        = htons(4444);
   sock = socket(AF_INET,SOCK_STREAM,0);
   bind(sock, (SOCKADDR *)&sin, sizeof(sin));

   listen(sock,0);

   while(1) {
       memset(buffer, '\0', BUFSIZ); /*on vide le buffer*/
      
       int sinsize = sizeof(csin);
       csock = accept(sock, (SOCKADDR *)&csin, &sinsize);

       recv(csock, buffer, BUFSIZ-1, 0);
       printf("%s\n",buffer);

       if(strstr(buffer,"!salut")) {
           sprintf(buffer, "Commen ça va ?\n");
           send(csock, buffer, sizeof(buffer), 0);
       }
   }
}

Franchement je voit pas d'ou ça peut venir, peut-être du coté du client ?

edit: Y'a les deux ^^ enfin du c++ juste pour les cin et cout si tu veux y'a une partie qui date de y'a lontemps et l'autre que je viens de reprendre en c++ c'est plus rapide je trouve, mais bon ça devrait pas être ça le problème? si ?

Lien vers le commentaire
Partager sur d’autres sites

#include <winsock2.h>                        /*socket*/
#include <stdio.h>                            /*printf*/
#pragma comment(lib, "ws2_32.lib")

void main()
{
  WSADATA WSAData;
  WSAStartup(MAKEWORD(2,0), &WSAData);

  SOCKET sock;
  SOCKET csock;
  SOCKADDR_IN sin;
  SOCKADDR_IN csin;
  char buffer[BUFSIZ];;
  sin.sin_addr.s_addr = htonl(INADDR_ANY);
  sin.sin_family      = AF_INET;
  sin.sin_port        = htons(4444);
  sock = socket(AF_INET,SOCK_STREAM,0);
  bind(sock, (SOCKADDR *)&sin, sizeof(sin));

  listen(sock,0);

  /* connection socket */
  int sinsize = sizeof(csin);
  csock = accept(sock, (SOCKADDR *)&csin, &sinsize);

  while(1) {
      memset(buffer, '\0', BUFSIZ); /*on vide le buffer*/
   
      recv(csock, buffer, BUFSIZ-1, 0);
      printf("%s\n",buffer);

      if(strstr(buffer,"!salut")) {
          sprintf(buffer, "Commen ça va ?\n");
          send(csock, buffer, sizeof(buffer), 0);
      }
  }
}

essai comme ca

edit de ton edit :

ce n'est pas le probleme, c'est juste que quand tu code du C++ et qu'il y a des fonctions préfaite en C++ pour faire celle que tu utilise en C, c'est beaucoup plus propre

c'est comme le mec qui fait du C++ et qui utilise des printf : code totalement pourrie

faut voir avec la STL

edit num 2 : c'est toujours bien de tester toutes les fonctions qui peuvent l'etre

comme le bind et le listen qui renvoie des codes de retour et qui peuvent etre faux

Lien vers le commentaire
Partager sur d’autres sites

Aparement ça fonctionne plus bien du coter serveur mais :

Voila ce que j'obtient du coter client :

client_server.JPG

Je pense que ça vient plus du client cette fois si, enfin je te remercie déjà pour ça je vais essayer de me débrouiller maintenant. Si j'ai un problème je serais ou m'adresser ^^.

Lien vers le commentaire
Partager sur d’autres sites

probleme de buffer ou d'envoie de donnée : un truc dans le genre

la boucle va peut etre trop vite...

je réétudie ton code client pour voir

#include <winsock2.h>      /*socket*/
#include <stdio.h>       /*printf*/
#include <iostream>
#pragma comment(lib, "ws2_32.lib")

void main()
{

char ip[256];
std::cout << "IP : ";
std::cin >> ip;
std::cout << std::endl;

WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);

SOCKET sock;
SOCKADDR_IN sin;
char buffer[BUFSIZ];
char msg[256];

sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_family      = AF_INET;
sin.sin_port        = htons(4444);
sock = socket(AF_INET,SOCK_STREAM,0);
bind(sock, (SOCKADDR *)&sin, sizeof(sin));


connect(sock, (SOCKADDR *)&sin, sizeof(sin));


while(1) {

std::cout << "MSG : ";
std::cin >> msg;

memset(buffer, '\0', BUFSIZ); /*on vide le buffer aussi ici */
sprintf(buffer, "%s\n", msg);
send(sock, buffer, sizeof(buffer), 0);


memset(buffer, '\0', BUFSIZ); /*on vide le buffer*/
recv(sock, buffer, BUFSIZ-1, 0);
printf("%s",buffer);

}


}/* fin du programme */

j'ai rajouter le vidage du buffer.

apres un tour de boucle tu ecrit dans le buffer sans le vider.

mais bon ca ne doit pas venir de la je pense

edit 1 : a force d'edite ca m'enerve.

passage sur msn pour la suite ^^

Lien vers le commentaire
Partager sur d’autres sites

Bon par manque d'envit de dormir j'ai finalement reussit à trouver le problème : remplacer tout les "BUFSIZ" et "BUFSIZE-1" par "sizeof(buffer)" et ça marche.

Client :

#include <winsock2.h>    	/*socket*/
#include <stdio.h>      	/*printf*/
#include <iostream>
#pragma comment(lib, "ws2_32.lib")

void main()
{
char ip[256];
std::cout << "IP : ";
std::cin >> ip;
std::cout << std::endl;

WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);

SOCKET sock;
SOCKADDR_IN sin;
char buffer[BUFSIZ];
char msg[256];

sin.sin_addr.s_addr = inet_addr(ip);
sin.sin_family      = AF_INET;
sin.sin_port        = htons(4444);
sock = socket(AF_INET,SOCK_STREAM,0);
bind(sock, (SOCKADDR *)&sin, sizeof(sin));

connect(sock, (SOCKADDR *)&sin, sizeof(sin));

while(1) {
 std::cout << "MSG : ";
 std::cin >> msg;

 memset(buffer, '\0', sizeof(buffer));
 sprintf(buffer, "%s\n", msg);
 send(sock, buffer, sizeof(buffer), 0);

 memset(buffer, '\0', sizeof(buffer));
 recv(sock, buffer, sizeof(buffer), 0);
 printf("%s\n",buffer);
} 

}

Server :

#include <winsock2.h>    	/*socket*/
#include <stdio.h>      	/*printf*/
#pragma comment(lib, "ws2_32.lib")

void main()
{

WSADATA WSAData;
WSAStartup(MAKEWORD(2,0), &WSAData);

SOCKET sock;
SOCKET csock;
SOCKADDR_IN sin;
SOCKADDR_IN csin;
char buffer[BUFSIZ];;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family      = AF_INET;
sin.sin_port        = htons(4444);
sock = socket(AF_INET,SOCK_STREAM,0);
bind(sock, (SOCKADDR *)&sin, sizeof(sin));

listen(sock,0);

/* connection socket */
int sinsize = sizeof(csin);
csock = accept(sock, (SOCKADDR *)&csin, &sinsize);

while(1) {
  memset(buffer, '\0', sizeof(buffer)); /*on vide le buffer*/
  recv(csock, buffer, sizeof(buffer), 0);
  printf("%s",buffer);

  if(strstr(buffer,"!salut")) {
     sprintf(buffer, "tu as dit salut\n");
     send(csock, buffer, sizeof(buffer), 0);
     printf("rply-> %s\n",buffer);
  } 

  if(strstr(buffer,"!hello")) {
     sprintf(buffer, "tu as dit hello\n");
     send(csock, buffer, sizeof(buffer), 0);
     printf("rply-> %s\n",buffer);
  }
 }
}

Voila peut-être que ça poura aider quelqu'un.

Et merci à keneda212.

Lien vers le commentaire
Partager sur d’autres sites

y'a juste un turc que je rajouterai pour faire plus propre et eviter des erreurs plus tard

dans le serveur

 while(1) {
 memset(buffer, '\0', sizeof(buffer)); /*on vide le buffer*/
 recv(csock, buffer, sizeof(buffer), 0);
 printf("%s",buffer);

 if(strstr(buffer,"!salut")) {
   
memset(buffer, '\0', sizeof(buffer)); // vider le buffer car dans le cas ou tu ecris une chaine plus petite que celle que tu recoie, il te restera les caractères de fin du buffer precedent

    sprintf(buffer, "tu as dit salut\n");
    send(csock, buffer, sizeof(buffer), 0);
    printf("rply-> %s\n",buffer);
 }

 if(strstr(buffer,"!hello")) {
memset(buffer, '\0', sizeof(buffer)); // idem
    sprintf(buffer, "tu as dit hello\n");
    send(csock, buffer, sizeof(buffer), 0);
    printf("rply-> %s\n",buffer);
 }
}
}

Lien vers le commentaire
Partager sur d’autres sites

Je ne sais pas trop comment l'implementer en C++ mais je sais qu'il existe les selector de file descriptor en C ( le fameux FD_SET ) accessible depuis les fonctions select() et pselect().

L'avantage c'est que les sockets sont non bloquantes (asynchrone) , tu boucle sur ton set de fd et tu peux ainsi verifier si leur etats ( READ WRITE CONNECT ACCEPT) changent (ce mecanisme s'effectue via /dev/poll ) et en fonction de cela leur attacher une fonction donnée.

En java on appele ca les NIO ( non blocking io ) et on peut leur attacher un handler directement ( c trop la classe je java ^^ )

En plus d'etre performant, ce fonctionnement est bcp plus logique a mon sens et permet de faire des handle de beaucoup de clients sans pour autant bouffer de la ressource ( un petit objet de pool de connexion a coté tu thread des workers apropriés et hop c fini :) )

Voila pour plus d'info man select :eeek2:

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...