用spserver实现类似ftp server的文件服务器,大家有什么好的建议?

67 views
Skip to first unread message

卡卡

unread,
Aug 4, 2009, 5:16:19 AM8/4/09
to spserver
SP_IocpLFServer server( "", 5555, new SP_FileHandlerFactory() );主控端口开在
5555上,我不想打开新端口,主控端口同时走控制协议和文件数据行不行?

lau stephen

unread,
Aug 4, 2009, 5:27:25 AM8/4/09
to spse...@googlegroups.com
通过细致的协议设计,是可以这样做的。但是要考虑一个因素:ftp 的控制端口和数据端口,貌似可以并行工作,在 LZ 的应用中是否需要这样的特性?

2009/8/4 卡卡 <karo...@gmail.com>:

卡卡

unread,
Aug 4, 2009, 5:50:44 AM8/4/09
to spserver
是的,比如在服务器在给某客户传文件数据,该客户在接收文件数据的同时还有可能同时请求目录,或者查看服务上的很它资源等等;
virtual int handle( SP_Request * request, SP_Response * response )
{
...
if( 0 == strcasecmp( line, "客户请求某文件" ) )
{
另外一个问题是:要在这儿用response 发送指定文件???? 文件数据很大,用for循环追加文件数据,最后
response 队列不是一下就overflow了吗??
}
...
}

lau stephen

unread,
Aug 4, 2009, 5:56:35 AM8/4/09
to spse...@googlegroups.com
对于文件的话,我建议用 file mapping 的方式。在 linux 下面是 mmap 这个系统调用,在 windows 也有类似的。

这样做首先需要实现 SP_MsgBlock 的子类,比如实现一个 SP_FileMappingMsgBlock 。
在 handle 函数中,打开文件进行 mapping ,然后把 mapping 出来的 buffer 指针放到
SP_FileMappingMsgBlock 中。

这个也是当初设计 SP_MsgBlock 的一个原因。

2009/8/4 卡卡 <karo...@gmail.com>:

Message has been deleted

卡卡

unread,
Aug 4, 2009, 6:13:05 AM8/4/09
to spserver
谢谢,非常佩服lau stephen的洞察力,我现在最需要处理的工作就是在spserver框架下要求server能连续发送大量数据,同时还能处
理该客户端的的其它请求;
Message has been deleted

卡卡

unread,
Aug 11, 2009, 3:47:10 AM8/11/09
to spserver
想请lau兄确认一下我在如下场情下用spserver是否合适?
做一个支持大约300人的文件服务器,客户端可以登陆,登出;客户端在线状态下,可以查看服务器上各文件目录,并可以随意选择文件下载;

lau stephen

unread,
Aug 11, 2009, 6:03:07 AM8/11/09
to spse...@googlegroups.com
之前提到的用 文件映射 的方式来发送文件,不知是否有实际测试过?
如果已经可以做到这一步,那么就已经解决了一个大问题了。

这里涉及到 登录 ,就是有权限控制。
另外,浏览目录和下载文件是否可以同时进行?

这里具体的业务处理还是比较复杂的。

spserver 的框架可以适应这些复杂的业务处理,但是真正要实现,中间还有很多的细节。

2009/8/11 卡卡 <karo...@gmail.com>:
> 想请lau兄确认一下我在如下场情下用spserver行不行?
> 做一个支持大约300人的文件服务器,客户端可以登陆,登出;客户端在线状态下,可以查看服务器上各文件目录,并可以随意选择文件下载;

卡卡

unread,
Aug 12, 2009, 10:46:43 PM8/12/09
to spserver
没有,这个项目还在做需求分析,没正式写代码,只用sperver写了些简单项的测试程序,前不久刚看到spserver,觉得它的线程池调度,任务管
理,还有框架都做的不错,所以想借用一下,你的回答让我增加了不少信心;我前天在另一个了地方卡住了,客户端底层用的是libevent,我在一个新线
程A中用调event_dispatch();其内部用select监控着若干handle,并阻塞在这儿,问题是当我的界面点退出时,如何通知A也停
止呢?
Message has been deleted

卡卡

unread,
Aug 12, 2009, 11:01:30 PM8/12/09
to spserver
刚开始我是在关闭程序时,kill工作线程的方式非正常退出的,很不爽.
后来看了两天libevent代码,感觉singal似乎可以解决我的问题,可是网上的例子都很简单,如下所示,它只写了singal处理流程,网上

部分的例子并没有讲如何触发它,可能是我没看到.
int called = 0;
static void signal_cb(int fd, short event, void *arg)
{
struct event *signal = arg;
if (called >= 2)
event_del(signal);
called++;

}


int main (int argc, char **argv)
{
struct event signal_int;
WSADATA wsaData;
WSAStartup(MAKEWORD(2,2), &wsaData);
/* Initalize the event library */
event_init();
/* Initalize one event */
event_set(&signal_int, SIGINT, EV_SIGNAL|EV_PERSIST,
signal_cb,
&signal_int);
event_add(&signal_int, NULL);
event_dispatch();
WSACleanup();
return (0);
}
后来我在signal.h文件中发现了raise接口,仔细一看,原来它就是做唤醒事件的接口;只要在退出时调用raise(SIGINT);(线程安

后面再考虑) ,然后signal_cb将所以注册的事件都删除就可以使工作线程正常退出了

lau stephen

unread,
Aug 14, 2009, 10:32:14 PM8/14/09
to spse...@googlegroups.com
通常要使得事件循环(select/poll/epoll)能够优雅地退出,需要做两个事情
1.事件循环通常使用一个退出标志位,当标志位被置位的时候,结束事件循环。
2.在需要退出的时候,有可能 select 正在等待事件,这个时候需要唤醒 select

通常要唤醒 select/poll/epoll ,一个常见的做法是产生一对 pipe ,
然后把读端注册到 select/poll/epoll 中,在 pipe 的 onread 事件中,设置退出的标志位。
应用程序保留着写端,当需要退出时,应用程序往 pipe 写一个字节,就可以保证唤醒事件循环。


2009/8/13 卡卡 <karo...@gmail.com>:

卡卡

unread,
Aug 18, 2009, 3:17:36 AM8/18/09
to spserver
嗯,用pipe唤醒select的方法很经典;

你上面问我:浏览目录和下载文件是否可以同时进行? 是的,我的应用中确有这种需要和操作,有什么要注意的吗?

lau stephen

unread,
Aug 18, 2009, 7:31:21 AM8/18/09
to spse...@googlegroups.com
如果需要同时进行,那么就需要类似 ftp 协议那样,分控制连接和数据连接。

2009/8/18 卡卡 <karo...@gmail.com>:
> 嗯,用pipe唤醒select的方法很经典;
>
> 你上面问我:浏览目录和下载文件是否可以同时进行? 是的,我的应用中确有这种需要和操作,有什么要注意的吗?

卡卡

unread,
Aug 19, 2009, 5:06:45 AM8/19/09
to spserver
我用ftp测过,多开了一套数据端口后,因为防火墙或者nat的原因,有时port模式通,pasv模式不通;有时pasv模式通,port不通,总之
问题变的复杂,罗嗦了,只用一个连接不能解决这个问题吗?

iunknown

unread,
Aug 19, 2009, 8:32:56 AM8/19/09
to spserver
在一个连接上,数据是按顺序发送的。
如果在发送一个大文件的过程中,又想浏览目录,目录信息要么夹杂到文件内容中,要么中断文件的传送。
如果夹杂到文件内容中,那么就需要设计一套复杂的协议,把文件分成多个小块,以便在小块之间可以传送目录信息。

把控制连接和数据连接分开,不一定就要按 ftp 的模式。
只要你的 client 能够连接到 server ,那么每个 client 就能够创建到 server 的第二个连接。

On Aug 19, 5:06 pm, 卡卡 <karonh...@gmail.com> wrote:
> 我用ftp测过,多开了一套数据端口后,因为防火墙或者nat的原因,有时port模式通,pasv模式不通;有时pasv模式通,port不通,总之
> 问题变的复杂,罗嗦了,只用一个连接不能解决这个问题吗?

卡卡

unread,
Aug 19, 2009, 11:29:15 PM8/19/09
to spserver
"只要你的 client 能够连接到 server ,那么每个 client 就能够创建到 server 的第二个连接"这就是ftp的pasv
的工作方式,如果server的第二条连接主动连client就是port方式;我就是很奇怪碰到这样的场景,我在外网开了个filezilla
server,该机器是朋友公司的环境,非我能控制,所在的环境可能有防火墙之类的,在我公司内网的工作机上开了filezilla clitent,
可是上个星期pasv还工作好好的,这个星期突然有问题了,第一条连外网21端口的可以成功连接,第二条连接总是无法connect服务器,最奇怪的是
把我公司的路由器重启一下后,第二条连接又可以成功了....~~我实在想不出是什么原因,崩溃....

因为上面的原因,我倾向把应用协议弄复杂一点,也希望在一条连接上实现在多个功能,你说这个方法和我想的一样;
但是如果为数据传输专门创建第二条连接,那么在spserver的什么地方管理该连接呢,要不要为该任务再创建一个线程呢?

Reply all
Reply to author
Forward
0 new messages