| Код |
#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 }
|
|