Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Программирование под Unix/Linux > класс Сокет


Автор: annushka89 4.6.2009, 17:21
помогите написать полноценный класс Сокет для Linux(TCP/IP).
или же поделитесь пожалуйста ссылкой или исходником у кого есть

очень надеюсь на Вашу помощь
спасибо

Автор: azesmcar 4.6.2009, 17:27
http://www.alhem.net/Sockets/download.html

Автор: andrew_121 6.6.2009, 15:54
Код


#ifndef __SOCKET_H__
#define __SOCKET_H__

/***************************************************************************/

#include <sys/types.h>
#ifdef __GNUC__
#    include <unistd.h>
#endif

#ifdef WIN32
#    include <winsock2.h>
#else
#    include <sys/socket.h>
#    include <netinet/in.h>
#    include <netdb.h>
#    include <arpa/inet.h>
#endif

#include "lstring.h"

/***************************************************************************/

const int MAXHOSTNAME = 200;
const int MAXCONNECTIONS = 30;
const int MAXRECV = 500;

/***************************************************************************/

class Socket {
public:
    Socket();
    virtual ~Socket();

    /* Server initialization */
    bool create();
    bool bind(const int port);
    bool listen() const;
    bool accept(Socket&) const;

    /* Client initialization */
    bool connect(const LString& host, const int port);

    /* Data Transimission */
    bool send(const LString&) const;
    int recv(LString&) const;

    /* Overloads for big blocks */
    bool sendall(const char*, int, int*) const;
    bool recvall(char*, int, int*) const;

    void set_non_blocking(const bool);
    bool is_valid() const { return m_sock != -1; }
private:
    int            m_sock;
    sockaddr_in    m_addr;
};

#endif



Код


#include <assert.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <io.h>
#include <iostream>

#include "socket.h"

#ifdef WIN32
#    include <ws2tcpip.h>
#endif

Socket::Socket() :m_sock(-1) {
    memset(&m_addr, 0, sizeof(m_addr));
}

Socket::~Socket() {
    if (is_valid()) { ::close(m_sock); }
}

/* Creates a socket. Both servers and clients use this method */
bool Socket::create() {
    m_sock = ::socket(AF_INET, SOCK_STREAM, 0);

    if (!is_valid()) { return false; }

    int on = 1;
    if (setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (const char*) &on, sizeof(on)) == -1) {
        return false;
    }

    return true;
}

/* Bind a server socket to a port */
bool Socket::bind(const int port) {
    if (!is_valid()) { return false; }

    m_addr.sin_family = AF_INET;
    m_addr.sin_addr.s_addr = INADDR_ANY;
    m_addr.sin_port = htons(port);

    int bind_return = ::bind(m_sock, (struct sockaddr*) &m_addr, sizeof(m_addr));

    return !(bind_return == -1);
}

/* listen to a server port */
bool Socket::listen() const {
    if (!is_valid()) { return false; }

    int listen_return = ::listen(m_sock, MAXCONNECTIONS);

    return !(listen_return == -1);
}

bool Socket::accept(Socket& new_socket) const {
    int addr_length = sizeof(m_addr);
    new_socket.m_sock = ::accept(m_sock, (sockaddr*)&m_addr, (socklen_t*)&addr_length);

    return !(new_socket.m_sock <= 0);
}

bool Socket::send(const LString& s) const {
    /* MSG_NOSIGNAL: Требует не посылать сигнал SIGPIPE, если
        при работе с ориентированным на поток сокетом другая
        сторона обрывает соединение.
        Мля, a в Bинде нет такой возможности(((
    */
#ifdef WIN32
    int status = ::send(m_sock, s.c_str(), s.size(), 0);
#else
    int status = ::send(m_sock, s.c_str(), s.size(), MSG_NOSIGNAL);
#endif

    return (status != -1);
}

/* Read data from the socket */
int Socket::recv(LString& s) const {
    char buf[MAXRECV + 1];

    s.clear();

    memset(buf, 0, MAXRECV + 1);

    int status = ::recv(m_sock, buf, MAXRECV, 0);

    if (status == -1) {
        std::cout << "status == -1   errno == " << errno << "  in Socket::recv\n";
        return 0;
    } else if (status == 0) {
        return 0;
    } else {
        s = buf;
        return status;
    }
}

bool Socket::sendall(const char* buf, int size, int* sending) const {

    int total = 0;
    int num;

    while (total < size) {
        num = ::send(m_sock, buf+total, size-total, 0);
        if(num == -1) { break; }
        total += num;
    }
    *sending = total;
    
    return (num != -1);
}

bool Socket::recvall(char* buf, int size, int* reciving) const {
    return false;
}

/* Connect a client socket to a server socket */
bool Socket::connect(const LString& host, const int port) {
    if (!is_valid()) { return false; }

    m_addr.sin_family = AF_INET;
    m_addr.sin_port = htons(port);

    int status = inet_pton(AF_INET, host.c_str(), (unsigned char*)&m_addr.sin_addr);

#ifndef WIN32
    if (errno == EAFNOSUPPORT) { return false; }
#endif
    status = ::connect(m_sock, (sockaddr *) &m_addr, sizeof(m_addr));

    return (status == 0);
}

void Socket::set_non_blocking(const bool b) {
#ifndef WIN32
    int opts;

    opts = fcntl(m_sock, F_GETFL);

    if (opts < 0) { return; }

    if (b) {
        opts = (opts | O_NONBLOCK);
    } else {
        opts = (opts & ~O_NONBLOCK);
    }

    fcntl(m_sock, F_SETFL, opts);
#else
#endif
}


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)