您的位置:首页 > 其它

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

2012-06-03 13:02 609 查看
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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息