一个简单的文件共享工程 -- 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;
}
}
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;
}
}
相关文章推荐
- 一个简单的文件共享工程 -- 功能概述
- 一个简单的文件共享工程 -- Head
- 一个简单的文件共享工程 -- TConnection
- 一个简单的文件共享工程 -- TMClient
- 一个简单的文件共享工程 -- FileServer
- 一个简单的文件共享工程 -- FileClient
- 一个简单的文件共享工程 -- 总结
- 今天学了一个简单的新技能Xcode6以后创建工程后没有.pch文件,所以来个技能--iOS开发
- 创建一个Android程序(简单介绍工程里面各个文件的作用)
- 共享文件夹—— 一个实现Mac与PC互传文件,维护同一个文件夹简单的方法
- 教你如何将工程中的一个功能模块提取成library库文件,供其他工程轻松接入,只需简单5步
- Skype for Business Server 2015-04-前端服务器-2-创建一个文件共享
- 创建一个Android程序(简单介绍工程里面各个文件的作用)
- 多个工程共享一个配置文件
- 在FPGA中简单的建立一个工程,并编写测试文件
- 一个共享XP、2003上文件与打印机简单易行的方法
- MFC:一个简单的多线程传送文件的实现 client端(2)
- 最快最简单的方式开通Win7的局域网文件共享,让所有Win系统无隔阂
- shmget 共享内存 同步读写文件一个进程写,多个进程读,读和写同步,边写边读
- 使用 POI创建一个简单的 Excel 文件