Gå til innhold

Noen som vet om noen enkle tcp libraries ?


Anbefalte innlegg

Videoannonse
Annonse

Jeg skrev en veldig enkel wrapper rundt POSIX sockets. Den burde funke under Win32 uten store forandringer.

 

client.hpp

Klikk for å se/fjerne innholdet nedenfor

#ifndef _client_hpp_
#define _client_hpp_

#include <string>

#include <sys/types.h>
#include <netdb.h>

#include "connection.hpp"

namespace Zsocket {

       class Client {
               public:
                       Client();

                       void set_port(short);
                       short get_port() const;

                       void set_host(std::string);
                       std::string get_host() const;

                       Connection connect();
                       Connection connect(const std::string, int);

               private:
                       Client(Client&);
                       Client& operator=(Client&);

                       sockaddr_in server;

                       bool host_set;
                       bool port_set;
       };

}
#endif

client.cpp

Klikk for å se/fjerne innholdet nedenfor
#include <iostream>
#include <exception>
#include <string>
#include <cstdlib>

#include <sys/socket.h>
#include <sys/types.h>

#include "client.hpp"
#include "exception.hpp"

namespace Zsocket {

       Client::Client() : host_set(false), port_set(false)
       {
       }

       void Client::set_port(short p)
       {
               server.sin_port = htons(p);
               port_set = true;
       }

       void Client::set_host(const std::string hn)
       {
               hostent* he = gethostbyname(hn.c_str());
               if(he == 0) {
                       herror("gethostbyname");
                       throw Exception("Unable to resolve host");
               }
               server.sin_addr = *((in_addr*)he->h_addr);

               host_set = true;
       }

       Connection Client::connect()
       {
               if(!port_set || !host_set)
                       throw Exception("Host and port most be set before connecting");

               server.sin_family = AF_INET;
               memset(&(server.sin_zero), '\0', 8);

               int sockfd = socket(AF_INET, SOCK_STREAM, 0);
               if(sockfd == -1) {
                       perror("socket");
                       throw Exception("Unable to get socket file descriptor");                }

               if(::connect(sockfd, (sockaddr*)&server, sizeof(sockaddr)) == -1) {
                       perror("connect");
                       throw Exception("Unable to connecto to server");
               }

               return Connection(sockfd);
       }

       Connection Client::connect(const std::string hn, int p)
       {
               set_host(hn);
               set_port(p);
               return connect();
       }

}

connection.hpp

Klikk for å se/fjerne innholdet nedenfor
#ifndef _connection_hpp_
#define _connection_hpp_

#include <string>

namespace Zsocket {

       class Connection {
               public:
                       Connection(int);
                       Connection(const Connection&);

                       std::string read(int);
                       int write(const std::string);
                       bool active();
                       void close();

               private:
                       int sockfd;
                       bool connection_active;
       };

}

#endif

connection.cpp

Klikk for å se/fjerne innholdet nedenfor
#include <cstdlib>

#include <sys/socket.h>

#include "connection.hpp"
#include "exception.hpp"

namespace Zsocket {

       Connection::Connection(int sfd) : sockfd(sfd)
       {
       }

       Connection::Connection(const Connection& cc)
       {
               sockfd = cc.sockfd;
               connection_active = true;
       }

       std::string Connection::read(int ss)
       {
               char ret[ss];
               if(recv(sockfd, &ret, ss, 0) == -1) {
                       perror("recv");
                       throw Exception("Error while receiving data");
               }

               return ret;
       }

       int Connection::write(const std::string buf)
       {
               int sent_bytes = send(sockfd, buf.c_str(), buf.length()+1, 0);
               if(sent_bytes == -1) {
                       perror("send");
                       throw Exception("Error while sending data");
               }

               return sent_bytes;
       }

       bool Connection::active()
       {
               return connection_active;
       }

       void Connection::close()
       {
               ::close(sockfd);
       }

}

server.hpp

Klikk for å se/fjerne innholdet nedenfor
#ifndef _server_hpp_
#define _server_hpp_

#include <string>
#include <cerrno>
#include <cstdlib>

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "connection.hpp"

namespace Zsocket {

       class Server {
               public:
                       Server();

                       void listen(short);
                       Connection accept();

               private:
                       sockaddr_in server;
                       sockaddr_in client;
                       int sockfd;
                       int backlog;
       };

}

#endif

server.cpp

Klikk for å se/fjerne innholdet nedenfor
#include <exception>

#include "server.hpp"

namespace Zsocket {

       Server::Server() : backlog(20)
       {
               sockfd = socket(AF_INET, SOCK_STREAM, 0);
               if(sockfd == -1) {
                       perror("socket");
               }

               server.sin_family = AF_INET;
               server.sin_addr.s_addr = INADDR_ANY;
               memset(&(server.sin_zero), '\0', 8);
       }

       void Server::listen(short port)
       {
               server.sin_port = htons(port);

               if(bind(sockfd, (sockaddr*)&server, sizeof(sockaddr)) == -1) {
                       perror("bind");
               }

               if(::listen(sockfd, backlog) == -1) {
                       perror("listen");
               }
       }

       Connection Server::accept()
       {
               socklen_t len = sizeof(sockaddr);

               int sfd = ::accept(sockfd, (sockaddr*)&client, &len);
               if(sfd == -1)
                       perror("accpt");

               Connection conn(sfd);
               return conn;
       }

}

exception.hpp

Klikk for å se/fjerne innholdet nedenfor
#ifndef _exception_hpp_
#define _exception_hpp_

#include <string>

namespace Zsocket {

       class Exception {
               public:
                       Exception(std::string ee) : errmsg(ee) { };
                       std::string what() { return errmsg; };
               private:
                       std::string errmsg;
       };

}

#endif

 

Den er som du ser ekstremt enkel, kanskje i det ytterste laget, men den funker for meg. :p Dessuten bør den ikke være vanskelig utvide hvis ønsket.

 

Edit:

For at den skal funke i windows, må headerene byttes ut, og så må det legges til en WSA_Startup elns et eller annet sted.

Endret av zirener
Lenke til kommentar

Nå vet ikke jeg hva du bruker av utviklingsverktøy, men ettersom jeg bruker SCons, bruker jeg følgende SConstruct-fil:

# Zsocket build
env = Environment()

env.SharedLibrary('zsocket', Split("""
src/client.cpp
src/server.cpp
src/connection.cpp
"""))

og kompilerer på følgende måte:

staale@thinkpad:~/programming/cpp/zsocket$ scons

 

Da får jeg i Linux en .so fil, noe som i Windows vil tilsvare en .dll fil. Denne bruker jeg når jeg linker serveren med programmet på dette viset:

# server build
server = Environment()
server.Append(CPPPATH='..', LIBPATH='..', LIBS='zsocket')
server.Program('server', Split("""
server.cpp
"""))

Her har jeg satt CPPPATH til '..', altså "mappen ett hakk tilbake", og det samme har jeg gjort med LIBPATH. Dette vil jo selvfølgelig variere alt ettersom hvor man har prosjektet sitt. I mitt tilfelle, er det i test-mappa i mappen der jeg har kompilert bibloteket, og da blir verdiene til CPPPATH og LIBPATH '..'.

 

staale@thinkpad:~/programming/cpp/zsocket/test$ scons

Kjører...

staale@thinkpad:~/programming/cpp/zsocket/test$ ./server

 

Kildekoden til serveren:

#include <iostream>
#include <sstream>

#include <server.hpp>
#include <connection.hpp>

using namespace std;
using namespace Zsocket;

int main(int argc, char* argv[])
{
       Server server;
       server.listen(2507);

       while(true) {
               Connection conn = server.accept();
               string buffer = conn.read(255);
               conn.write("This is the server speaking!");
               conn.close();
       }

       return 0;
}

 

Skrik om det var noe som var utydelig. :)

Endret av zirener
Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...