Librairie pour sockets c++

Contenu du snippet

Voici une source permettant de créer des clients et des serveurs basées sur les sockets pour système UNIX.

Pour cela il suffit d'implémenter la méthode virtuelle interaction.
La partie connexion est gérée automatiquement. Chaque connexion d'un client est gérée par un thead.

note : ne fonctionne pas sous windows.

La source contient un exemple d'implémentation d'un client et d'un serveur.

Le serveur cle/valeur implémente les operations suivantes:
- GET CLE
- PUT CLE VALEUR
- DEL CLE
- QUIT

Les applications doivent être lancées à partir du terminal :
serveur : ./server-word-word 23000
client : ./client-word-word localhost 23000

telecharger source : http://www.megaupload.com/?d=VKWF64L6

Source / Exemple :


#ifndef _SOCKET_HH_
#define _SOCKET_HH_

#include "libsocketException.h"

extern "C"
{
	#include <stdlib.h>
	#include <stdio.h>
};

#include <iostream>
#include <sstream>

namespace libsocket
{
 /*____________________________________________________________________________________________*/
  /** 

  • une socket.
    • /
class Socket { protected: int _fd;// descripteur de la socket virtual void socket() = 0; virtual void bind(int port) = 0; public: Socket(); virtual void close()=0; void setFd(int fd); int getFd(); }; } #endif #include "libsocketTcp.h" extern "C" { #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <errno.h> #include <netinet/in.h> #include <string.h> }; #include <iostream> #include <sstream> #include <pthread.h> // librairie thread namespace libsocket { /*************************************************************************/ /** Server **/ /*************************************************************************/ /*_____________________________________________________________________________*/ /**
    • /
void ServerTcp::run(int port) { socket(); bind(port); listen(10); loop(); } /*_____________________________________________________________________________*/ /**
  • boucle d'intéraction
    • /
void ServerTcp::loop() { /*while (true) { SocketTcp client; accept(client); std::cout<<"apres:"<<client.getFd()<<std::endl; if(fork() == 0) { printf("connexion \n"); interaction(client); client.close(); printf("deconnexion \n"); exit(0); } }*/ while (true) { SocketTcp* client = new SocketTcp(); accept(*client); pthread_t num_thread[1]; void * tab[2] = {this,client}; if (pthread_create(&num_thread[0], NULL, (void *(*)(void *))&ServerTcp::startThread,tab) == -1) perror ("problème creation du thread\n"); } } /*_____________________________________________________________________________*/ /**
  • on est obligé de passer par une métode static pour utiliser un thread
    • /
void* ServerTcp::startThread ( void* Parameters[] ) { ServerTcp* server = reinterpret_cast<ServerTcp*>(Parameters[0]);//recupere l'objet Server SocketTcp* client = reinterpret_cast<SocketTcp*>(Parameters[1]);//recupere la socket client server->runThread(client); } /*_____________________________________________________________________________*/ /**
  • methode appelé par le thread
    • /
void ServerTcp::runThread(SocketTcp* client) { printf("connexion\n"); interaction(*client);//appel de la methode virtuelle interaction client->close();//fermeture de la socket delete client;//liberation du pointeur client déclaré dans Server::loop printf("deconnexion \n"); pthread_exit(NULL);//detruit le thread } /*************************************************************************/ /** Client **/ /*************************************************************************/ /*_____________________________________________________________________________*/ /**
  • utilise les méthodes de Socket pour établir une connexion
  • à une serveur lancer l'interaction
    • /
void ClientTcp::run(const char* host, int port) { socket(); connect(host,port); interaction(); close(); } /*_____________________________________________________________________________*/ /**
  • cette variante appelle la précédente
    • /
void ClientTcp::run(string& host, int port) { run(host.c_str(),port); } }; #include "socketTcp.h" #include <iostream> using namespace std; namespace libsocket { /*_____________________________________________________________________________*/ /**
  • invoque l'appel système socket
    • /
void SocketTcp::socket() { _fd = ::socket(PF_INET, SOCK_STREAM, 0); // appel la fonction socket de c. if (_fd < 0) throw ErrnoExcept("socket"); } /*_____________________________________________________________________________*/ void SocketTcp::connect(const char* host, int port) { ostringstream os; os<<port; socket(); struct addrinfo *serv_addr = 0; int k = getaddrinfo(host,os.str().c_str(),0,&serv_addr);//obtebir une structure d adresse if(k != 0) throw ErrnoExcept("getaddrinfo"); while(k=::connect(_fd,serv_addr->ai_addr,serv_addr->ai_addrlen)) { if(k<0) if (errno==EAGAIN || errno==EINTR) continue; else throw ErrnoExcept("serveur indisponible"); } freeaddrinfo(serv_addr); } /*_____________________________________________________________________________*/ /**
  • ferme la socket
    • /
void SocketTcp::close() { while (_fd >= 0) { int r = ::close(_fd); if (r < 0) { if (errno == EINTR) continue; else throw ErrnoExcept("close"); } break; } _fd = -1; } /*_____________________________________________________________________________*/ /**
  • lie la socket au port sur toutes les interfaces.
    • /
void SocketTcp::bind(int port) { struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (::bind(_fd, (struct sockaddr *) &addr, sizeof(addr))==-1) throw ErrnoExcept("bind"); } /*_____________________________________________________________________________*/ /**
  • \c listen pour indiquer qu'on va écouter sur cette socket.
    • /
void SocketTcp::listen(int backlog) { if (::listen(_fd, backlog)==-1) throw ErrnoExcept("listen"); } /*_____________________________________________________________________________*/ /**
  • Pour attendre et accepter une demande de connexion d'un client. C
    • /
void SocketTcp::accept(Socket& client) { while (true) { int cli = ::accept(_fd, NULL, NULL); if (cli < 0) { //cas exceptionnels de fonctionnement normal if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) continue; else throw ErrnoExcept("accept"); } client.setFd(cli); break; } } /*_____________________________________________________________________________*/ /**
  • écrit sur la socket exactement n octets pointés par buf.
    • /
void SocketTcp::write(const char* buf, int n) { while (n > 0) { int k = ::write(_fd, buf, n); if (k < 0) { if (errno == EAGAIN || errno == EINTR) continue; else throw ErrnoExcept("write"); } buf += k; n -= k; } } /*_____________________________________________________________________________*/ /**
  • ecrit sur la socket en calculant elle-même la
  • longueur de la chaîne de caractères.
    • /
void SocketTcp::write(const char* buf) { write(buf, strlen(buf)+1);//+1 pour compter le '\0' } /*_____________________________________________________________________________*/ /** /**
  • Pour attendre et accepter une demande de connexion d'un client.
    • /
void SocketTcp::write(const string& buf) { write(buf.c_str(), buf.length()+1);//+1 pour compter le '\0' } /*_____________________________________________________________________________*/ void SocketTcp::read(char *buf,int n) { while (n > 0) { int k = ::read(_fd, buf, n); if (k < 0) if (errno == EAGAIN || errno == EINTR) continue; else throw ErrnoExcept("read"); buf += k; n -= k; } } /*_____________________________________________________________________________*/ /**
  • lit sur la socket exactement n octets et les retourne sous
la forme d'un string. (ne pas compter le caractère de fin de chaine '\0')
    • /
string SocketTcp::read(int n) { char mes[n+1]; //a corriger !! read(mes,n); int taille = strlen(mes); if(mes[taille] != '\0') mes[taille+1] = '\0'; return (string) mes; } /*_____________________________________________________________________________*/ /**
  • lire un entier
    • /
int32_t SocketTcp::readInt32() { int32_t v; read((char *) &v,sizeof(v)); return ntohl(v); } /*_____________________________________________________________________________*/ /**
  • ecrire un entier
    • /
void SocketTcp::writeInt32(int i) { int32_t v = htonl(i); write (( const char *) &v,sizeof(v)); } /*_____________________________________________________________________________*/ /**
  • lit une ligne de texte et retourne un string (sans le \n)
    • /
string SocketTcp::readLine() { char c; ostringstream os; while(true) { int k = ::read(_fd,&c,1); if (k <= 0)//si k==0 on leve une exception pour eviter une boucle infinie if (errno == EAGAIN || errno == EINTR) continue; else throw ErrnoExcept("readline"); if(c == EOF || c == '\0' || c == '\n') break; else os << c; } return os.str(); } /*_____________________________________________________________________________*/ /**
  • lit un mot délimité par un espaces.
    • /
string SocketTcp::readWord() { char c; ostringstream res ; int k; //supprime les espaces while(true) { k = ::read(_fd,&c,1); if (k <= 0) //si k==0 on leve une exception pour eviter une boucle infinie if (errno == EAGAIN || errno == EINTR) continue; else throw ErrnoExcept("readword"); if(c == EOF || c == '\n' || c == '\0') return ""; if(!isspace(c)) { res<<c; break; } } //lecture d'un mot while(true) { k= ::read(_fd,&c,1); if (k <= 0) if (errno == EAGAIN || errno == EINTR) continue; else throw ErrnoExcept("readword"); if(c == EOF || c == '\0' || c == '\n' || isspace(c)) break; else res << c; } return res.str(); } } #include "socketUdp.h" #include <iostream> using namespace std; namespace libsocket { /*_____________________________________________________________________________*/ /**
  • invoque l'appel système socket
    • /
void SocketUdp::socket() { _fd = ::socket(AF_INET, SOCK_DGRAM, 0); // appel la fonction socket de c. if (_fd < 0) throw ErrnoExcept("socket"); } /*_____________________________________________________________________________*/ /**
  • ferme la socket
    • /
void SocketUdp::close() { while (_fd >= 0) { int r = ::close(_fd); if (r < 0) { if (errno == EINTR) continue; else throw ErrnoExcept("close"); } break; } _fd = -1; } /*_____________________________________________________________________________*/ /**
  • lie la socket au port sur toutes les interfaces.
    • /
void SocketUdp::bind(int port) { this->addr.sin_family = AF_INET; this->addr.sin_port = htons(port); this->addr.sin_addr.s_addr = htonl(INADDR_ANY); if (::bind(this->_fd, (struct sockaddr *) &this->addr, sizeof(this->addr))!=0) throw ErrnoExcept("bind"); } /*_____________________________________________________________________________*/ /**
  • envoyer un message.
    • /
void SocketUdp::sendto(const char* mes) { ::sendto(this->getFd(),mes,strlen(mes)+1,0,(struct sockaddr*)&this->addr,sizeof(addr)); } /*_____________________________________________________________________________*/ /**
  • envoyer un message.
    • /
void SocketUdp::sendto(string mes) { sendto(mes.c_str()); } /*_____________________________________________________________________________*/ /**
  • recevoir un message.
    • /
string SocketUdp::recvfrom(int n) { char mes[n+1]; int flag = ::recvfrom(this->getFd(),mes,n,0,(struct sockaddr*)&this->addr,&this->lg_app); int taille = strlen(mes); if(mes[taille] != '\0') mes[taille+1] = '\0'; return (string) mes; } }

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.