一个简单的文件共享工程 -- TMServer

TMServer是一个简单的文件共享工程,其核心文件TMServer.h包含关键功能。文章可能详细介绍了如何使用和理解这个工程,涉及迭代器、结构体、路径处理、命令行参数以及空指针等概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TMServer文件夹中文件:

TMServer.h:

#ifndef __TCP_MULTIPLEXING_SERVER_H__
#define __TCP_MULTIPLEXING_SERVER_H__

#include <dirent.h>
#include <sys/select.h>
#include <vector>
using std::vector;

#include "../TConnection/TConnection.h"
#include "../Head/Uncopy.h"

class TMServer : public TConnection, public Uncopy
{
public:
    TMServer(const char * host, const char * serv);
    virtual ~TMServer();

public:
    void mainloop();

protected:
    struct ConnNode
    {
    public:
        ConnNode(int connfd, unsigned short ulen);
        ConnNode(const ConnNode &);
        ~ConnNode();
        ConnNode & operator = (const ConnNode &);

    public:
        void destroy();

    public:
        int              sockfd;
        bool             rcvdat;
        unsigned short   lowlen;
        char             cwd[PATH_MAX + 1];

        static char      root[PATH_MAX + 1];
    };

protected:
    virtual bool handle(ConnNode & conn, unsigned char cmd, 
                        char * data, unsigned short uslen) = 0;

protected:
    bool accept();
    void close(int & index);
    bool checksock();
    void adjustcwd();

protected:
    int               m_listenfd;
    vector<ConnNode>  m_acceptcn;

    int               m_maxfd;
    fd_set            m_masterset;
};

#endif
TMServer.cpp:

#include <errno.h>
#include <dirent.h>
#include <cstdio>
#include <cstring>
#include <cassert>

#include "../ByteStream/ByteStream.h"
#include "../Head/Command.h"
#include "TMServer.h"

char TMServer::ConnNode::root[PATH_MAX + 1];

TMServer::TMServer(const char * host, const char * serv) : m_listenfd(-1)
{
    m_listenfd = listen(host, serv);
    FD_ZERO(&m_masterset);
    FD_SET(m_listenfd, &m_masterset);
    m_maxfd = m_listenfd;

    getcwd(ConnNode::root, PATH_MAX + 1);
    if ('/' != ConnNode::root[strlen(ConnNode::root) - 1]) {
        strcat(ConnNode::root, "/share/");
    }
    else {
        strcat(ConnNode::root, "share/");
    }
    mkdir(ConnNode::root, DIR_MODE);
}

TMServer::~TMServer()
{
    if (-1 != m_listenfd) {
        close(m_listenfd);
    }

    vector<ConnNode>::iterator iter = m_acceptcn.begin();
    while (m_acceptcn.end() != iter) {
        iter->destroy();
        ++iter;
    }
}

void TMServer::mainloop()
{
    int     nsel;
    fd_set  rset;
    char    buff[BUFFSIZ];

    for ( ; ; ) {
        rset = m_masterset;
        if (-1 == (nsel = select(m_maxfd + 1, &rset, NULL, NULL, NULL))) {
            printf("select error: %s\n", strerror(errno));
            if (!checksock()) {
                break;
            }
            break;
            continue;
        }

        if (FD_ISSET(m_listenfd, &rset)) {
            accept();
            if (0 == --nsel) {
                continue;
            }
        }

        for (int i = 0; i < m_acceptcn.size() && nsel > 0; ++i) {
            ConnNode & conn = m_acceptcn[i];
            if (FD_ISSET(conn.sockfd, &rset)) {
                --nsel;
                if (!conn.rcvdat) {
                    assert(sizeof(unsigned short) == conn.lowlen);
                    if (!recv(conn.sockfd, buff, conn.lowlen)) {
                        close(i);
                        continue;
                    }
                    IBStream is(buff, conn.lowlen);
                    is >> conn.lowlen;
                    assert(conn.lowlen > 0);
                    if (!setrcvlow(conn.sockfd, conn.lowlen)) {
                        close(i);
                        continue;
                    }
                    conn.rcvdat = true;
                }
                else {
                    assert(sizeof(unsigned char) <= conn.lowlen);
                    if (!recv(conn.sockfd, buff, conn.lowlen)) {
                        close(i);
                        continue;
                    }
                    IBStream is(buff, conn.lowlen);
                    unsigned char cmd;
                    is >> cmd;
                    if (!handle(conn, cmd, buff + is.tell(), 
                                conn.lowlen - is.tell())) {
                        close(i);
                        continue;
                    }
                    conn.lowlen = sizeof(unsigned short);
                    if (!setrcvlow(conn.sockfd, conn.lowlen)) {
                        close(i);
                        continue;
                    }
                    conn.rcvdat = false;
                }
            }
        }
    }
}

bool TMServer::accept()
{
    int  sockfd;

    if (-1 == (sockfd = TConnection::accept(m_listenfd))) {
        return(false);
    }

    if (!setrcvlow(sockfd, sizeof(unsigned short))) {
        ::close(sockfd);
        return(false);
    }
    setsndbuf(sockfd, 16384);
    setrcvbuf(sockfd, 16384);

    FD_SET(sockfd, &m_masterset);
    if (sockfd > m_maxfd) {
        m_maxfd = sockfd;
    }

    m_acceptcn.push_back(ConnNode(sockfd, sizeof(unsigned short)));

    printf("new client connected\n");

    return(true);
}

void TMServer::close(int & index)
{
    ConnNode & conn = m_acceptcn[index];

    if (-1 != conn.sockfd) {
        FD_CLR(conn.sockfd, &m_masterset);
    }
    conn.destroy();

    int ilast = m_acceptcn.size() - 1;
    if (ilast > index) {
        ConnNode & last = m_acceptcn[ilast];
        conn = last;
        last.sockfd = -1;
    }

    m_acceptcn.pop_back();

    --index;

    printf("close bad connection\n");
}

bool TMServer::checksock()
{
    struct stat sbuf;
    if (-1 == fstat(m_listenfd, &sbuf)) {
        printf("listen socket except\n");
        return(false);
    }
    for (int i = 0; i < m_acceptcn.size(); ++i) {
        ConnNode & conn = m_acceptcn[i];
        if (-1 == fstat(conn.sockfd, &sbuf)) {
            close(i);
        }
    }
    return(true);
}

void TMServer::adjustcwd()
{
    struct stat sbuf;
    vector<ConnNode>::iterator iter = m_acceptcn.begin();
    while (m_acceptcn.end() != iter) {
        if (-1 == lstat(iter->cwd, &sbuf)) {
            strcpy(iter->cwd, ConnNode::root);
        }
        ++iter;
    }
}

TMServer::ConnNode::ConnNode(int connfd, unsigned short ulen)
 : sockfd(connfd), rcvdat(false), lowlen(ulen)
{
    strcpy(cwd, root);
}

TMServer::ConnNode::ConnNode(const ConnNode & other)
 : sockfd(other.sockfd), rcvdat(other.rcvdat), lowlen(other.lowlen)
{
    strcpy(cwd, other.cwd);
}

TMServer::ConnNode::~ConnNode()
{
    /* do not call destory() */
}

TMServer::ConnNode & TMServer::ConnNode::operator = (const ConnNode & other)
{
    if (&other != this) {
        destroy();
        sockfd = other.sockfd;
        rcvdat = other.rcvdat;
        lowlen = other.lowlen;
        strcpy(cwd, other.cwd);
    }
    return(*this);
}

void TMServer::ConnNode::destroy()
{
    if (-1 != sockfd) {
        ::close(sockfd);
        sockfd = -1;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值