⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 socket.cpp

📁 一个UNIX/LINUX下的基于内容的过滤服务器源代码
💻 CPP
字号:
//Please refer to http://dansguardian.org/?page=copyright2//for the license for this code.//Written by Daniel Barron (daniel@jadeb//.com).//For support go to http://groups.yahoo.com/group/dansguardian//  This program is free software; you can redistribute it and/or modify//  it under the terms of the GNU General Public License as published by//  the Free Software Foundation; either version 2 of the License, or//  (at your option) any later version.////  This program is distributed in the hope that it will be useful,//  but WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the//  GNU General Public License for more details.////  You should have received a copy of the GNU General Public License//  along with this program; if not, write to the Free Software//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA#include <syslog.h>#include "Socket.hpp"#include <csignal>#ifdef __BSD	#include <sys/wait.h>#else	#include <wait.h>#endif#include <fcntl.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/time.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pwd.h>#include <cerrno>#include <unistd.h>#include <string>#include <stdexcept>// This class contains client and server Internet socket init and handling// code as well as functions for testing and working with the socket FDs.Socket::Socket() :timeout(5), isclosed(false), isused(false) {    sck_inet = socket(AF_INET, SOCK_STREAM, 0);    memset(&my_adr_inet, 0, sizeof my_adr_inet);    memset(&peer_adr_inet, 0, sizeof peer_adr_inet);    my_adr_inet.sin_family = AF_INET;    peer_adr_inet.sin_family = AF_INET;    peer_adr_inet_length = sizeof(struct sockaddr_in);}Socket::~Socket() {  // closing of fd is only automatic if socket not used    if (!isused && !isclosed) {        ::close(sck_inet);    }}// For creating a socket from the 3 things that make a socketSocket::Socket(int newfd, struct sockaddr_in myip, struct sockaddr_in peerip) :timeout(5), isclosed(false), isused(true) {    sck_inet = newfd;    memset(&my_adr_inet, 0, sizeof my_adr_inet);  // ***    memset(&peer_adr_inet, 0, sizeof peer_adr_inet);  // ***    my_adr_inet.sin_family = AF_INET;  // *** Fix suggested by    peer_adr_inet.sin_family = AF_INET;  // *** Christopher Weimann    my_adr_inet = myip;    peer_adr_inet = peerip;    peer_adr_inet_length = sizeof(struct sockaddr_in);}void Socket::reset() {    ::close(sck_inet);    timeout = 5;    isclosed = false;    isused = false;    sck_inet = socket(AF_INET, SOCK_STREAM, 0);    memset(&my_adr_inet, 0, sizeof my_adr_inet);    memset(&peer_adr_inet, 0, sizeof peer_adr_inet);    my_adr_inet.sin_family = AF_INET;    peer_adr_inet.sin_family = AF_INET;    peer_adr_inet_length = sizeof(struct sockaddr_in);}int Socket::connect(std::string ip, int port) {  // to make a connection to a serv    isused = true;    int len_inet = sizeof my_adr_inet;    peer_adr_inet.sin_port = htons(port);    inet_aton(ip.c_str(), &peer_adr_inet.sin_addr);    return ::connect(sck_inet, (struct sockaddr *) &peer_adr_inet, len_inet);}int Socket::bind(int port) {  // to bind a socket to a port    isused = true;    int len_inet = sizeof my_adr_inet;    int i = 1;    setsockopt(sck_inet, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));    my_adr_inet.sin_port = htons(port);    return ::bind(sck_inet, (struct sockaddr *) &my_adr_inet, len_inet);}int Socket::bind(std::string ip, int port) {  // to bind a socket to port,ip                                         // for hetrogenious machines    isused = true;    int len_inet = sizeof my_adr_inet;    int i = 1;    setsockopt(sck_inet, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));    my_adr_inet.sin_port = htons(port);    my_adr_inet.sin_addr.s_addr = inet_addr(ip.c_str());    return ::bind(sck_inet, (struct sockaddr *) &my_adr_inet, len_inet);}int Socket::listen(int queue) {  // mark a socket as a listening server sockt    return ::listen(sck_inet, queue);}Socket Socket::accept() {  // receive the incomming connection    peer_adr_inet_length = sizeof(struct sockaddr_in);    // OS X defines accept as:    // int accept(int s, struct sockaddr *addr, int *addrlen);    // but everyone else as:    // int accept(int s, struct sockaddr *addr, socklen_t *addrlen);#ifdef __DARWIN    int newfd = ::accept(sck_inet, (struct sockaddr *) &peer_adr_inet, (int *)&peer_adr_inet_length);#else    int newfd = ::accept(sck_inet, (struct sockaddr *) &peer_adr_inet, &peer_adr_inet_length);#endif    Socket s(newfd, my_adr_inet, peer_adr_inet);    return s;}std::string Socket::getPeerIP() {  // find the ip of the client connecting to us    return inet_ntoa(peer_adr_inet.sin_addr);}int Socket::getPeerSourcePort() {  // find the port of the client connecting to us    return ntohs(peer_adr_inet.sin_port);}int Socket::getFD() {    return sck_inet;}void Socket::setFD(int newfd) {    sck_inet = newfd;}void Socket::close() {  // close the socket (fd)    ::close(sck_inet);    isclosed = true;}void Socket::setTimeout(int t) {  // set the socket-wide timeout    timeout = t;}int Socket::getTimeout() {    return timeout;}bool Socket::checkForInput() {  // non-blocking check    fd_set fdSet;    FD_ZERO(&fdSet);  // clear the set    FD_SET(sck_inet, &fdSet);  // add fd to the set    timeval t;  // timeval struct    t.tv_sec = 0;    t.tv_usec = 0;    if (Socket::selectEINTR(sck_inet + 1, &fdSet, NULL, NULL, &t) < 1) {        return false;    }    return true;}void Socket::checkForInput(int timeout) throw (exception)  {                                            // blocks if socket blocking                                            // until timeout    fd_set fdSet;    FD_ZERO(&fdSet);  // clear the set    FD_SET(sck_inet, &fdSet);  // add fd to the set    timeval t;  // timeval struct    t.tv_sec = timeout;    t.tv_usec = 0;    if (Socket::selectEINTR(sck_inet + 1, &fdSet, NULL, NULL, &t) < 1) {        string err("select() on input: ");        throw runtime_error(err + (errno? strerror(errno) : "timeout"));    }}bool Socket::readyForOutput() {  // non-blocking check    fd_set fdSet;    FD_ZERO(&fdSet);  // clear the set    FD_SET(sck_inet, &fdSet);  // add fd to the set    timeval t;  // timeval struct    t.tv_sec = 0;    t.tv_usec = 0;    if (Socket::selectEINTR(sck_inet + 1, NULL, &fdSet, NULL, &t) < 1) {        return false;    }    return true;}void Socket::readyForOutput(int timeout) throw(exception) {                                            // blocks if socket blocking                                            // until timeout    fd_set fdSet;    FD_ZERO(&fdSet);  // clear the set    FD_SET(sck_inet, &fdSet);  // add fd to the set    timeval t;  // timeval struct    t.tv_sec = timeout;    t.tv_usec = 0;    if (Socket::selectEINTR(sck_inet + 1, NULL, &fdSet, NULL, &t) < 1) {        string err("select() on output: ");        throw runtime_error(err + (errno? strerror(errno) : "timeout"));    }}int Socket::getline(char* buff, int size, int timeout) throw(exception) {    char b[1];    int rc;    int i = 0;    b[0] = 0;    while(i < (size - 1)) {        rc = readFromSocket(b, 1, 0, timeout);        if (rc < 0) {            throw runtime_error(string("Can't read from socket: ") + strerror(errno));  // on error        }        if (rc == 0) {  // eof, other end closed so            b[0] = '\n'; // force it to return what read        }        buff[i] = b[0];        i++;        if (b[0] == '\n') {            buff[i - 1] = '\0';            break;        }    }    buff[i] = '\0';    return i;}void Socket::writeString(const char* line) throw(exception) {    int l = strlen(line);    if (!writeToSocket((char*)line, l, 0, timeout)) {        throw runtime_error(string("Can't write to socket: ") + strerror(errno));    }}void Socket::writeToSockete(char* buff, int len, unsigned int flags, int timeout) throw(exception) {  if (!Socket::writeToSocket(buff, len, flags, timeout)) {      throw runtime_error(string("Can't write to socket: ") + strerror(errno));  }}bool Socket::writeToSocket(char* buff, int len, unsigned int flags, int timeout) {    int actuallysent = 0;    int sent;    while (actuallysent < len) {        try {            readyForOutput(timeout);  // throws exception on error or timeout        } catch (exception& e) {            return false;        }        sent = send(sck_inet, buff + actuallysent, len - actuallysent, 0);        if (sent < 0) {            if (errno == EINTR) {                continue;  // was interupted by signal so restart            }            return false;        }        if (sent == 0) {            return false; // other end is closed        }        actuallysent += sent;    }    return true;}// read a specified expected amount and return what actually readint Socket::readFromSocketn(char* buff, int len, unsigned int flags, int timeout) {    int cnt, rc;    cnt = len;    while (cnt > 0) {        try {            checkForInput(timeout);  // throws exception on error or timeout        } catch (exception& e) {            return -1;        }        rc = recv(sck_inet, buff, len, flags);        if (rc < 0) {            if (errno == EINTR) {                continue;            }            return -1;        }        if (rc == 0) { // eof            return len - cnt;        }        buff += rc;        cnt -= rc;    }    return len;}// read what's available and return how much readint Socket::readFromSocket(char* buff, int len, unsigned int flags, int timeout) {    int rc;    try {        checkForInput(timeout);    } catch (exception& e) {        return -1;    }    while (true) {        rc = recv(sck_inet, buff, len, flags);        if (rc < 0) {            if (errno == EINTR) {                continue;            }        }        break;    }    return rc;}// a wrapper for select so that it auto-restarts after an ENINTRint Socket::selectEINTR(int numfds, fd_set * readfds, fd_set * writefds, fd_set * exceptfds, struct timeval * timeout) {    int rc;    errno=0;    while (true) {  // using the while as a restart point with continue        rc = select(numfds, readfds, writefds, exceptfds, timeout);        if (rc < 0) {            if (errno == EINTR) {                continue;  // was interupted by a signal so restart            }        }        break;  // end the while    }    return rc;  // return status}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -