背景:
阅读文章

用LPC做SERVER

[日期:2007-05-11] 来源:  作者: [字体: ]

//written by super
偶的MUD编程经历之用LPC做SERVER。
最近把学的TCP/IP的网络知识运用了起来。就想着用LPC做一个SERVER玩玩。
首先,LPC支持的网络接口函数有:
socket_accept()
socket_acquire()
socket_address()
socket_bind()
socket_close()


socket_connect()
socket_create()
socket_error()
socket_listen()
socket_release()
socket_status()
socket_write()
大家都知道一个SERVER要运转起来,首先要先create()一个插口。
然后把某一知名端口通过blind()和create()出来的那个插口绑定起来。
然后把这一端口至于贞听(listen)状态。然后就通过accept()来接受客户端的
连接请求。
我们可以把上面这些过程看成是服务器的初始化。就可以集成为一个过程。
int s;
int server_init()
{
        int err;
        s = socket_create(STREAM,"create_callback","create_close");
        if (s < 0)
                return 0;
        err = socket_bind(s,PORT_NUM);
        if (err!=EESUCCESS)
                return 0;
        err = socket_listen(s,"listen_callback");
        if (err!=EESUCCESS)
                return 0;
        return 1;
}
这就是一个有连接状态的服务器的初始化的例子了。
然后就是决定怎么来socket_accept()新的连接了。
按照TCP/IP的原理,socket_accept()的过程应该是由一个
死循环的进程来处理的。只要accept()返回的值大于0,那这个返回的值就是
一新接口的描叙符。
但是在LPC里面,它不支持用户来FOLK()进程,所以说,它就把以上那死循环
包装好了,做成一个listen的参数,也就是socket_listen()的argument 2.
然后是,如果有连接请求,就马上调用以socket_listen()的第二个参数为名字
的过程。
void listen_callback(int fd)
{
        int new_fd = socket_accept(fd,"in_read_callback","in_write_callback");
        do_next(new_fd);
        return;
}
然后服务器和客户端就可以通过这个new_fd来进行通讯了。
如果这个时候服务器收到了客户端write()过来的消息。
就会自动调用in_read_callback()过程。
其实这个过程也是把一个死循环read()的过程封装起来了。
然后如果要通讯的话,就可以这样写:
void in_read_callback(int fd,string mess)
{}
这里的fd就是通讯的插口,mess就是收到的信息。
然后在这个过程里面可以用sscanf(mess,)来把mess处理成理想的格式
但是这时要注意一点。。要把传过来的mess最后面的/n/r,/n,/r,/r/n四种符号过滤掉。

要不然的话,你的程序可能会把这些东西弄错的。
然后就可以一直通讯到SERVER不想再通讯时就发送一个socket_close(fd)
但是这个命令是根据什么底层函数封装起来的偶就不太清楚了,所以客户端很难
捕捉到这个信息,除非也是用LPC做客户端。
下面附一简单程序:
//created by super at 2001
#include < ansi.h >
#include < socket_err.h >
#include < net/socket.h >
#include < net/socket_errors.h >
#include < globals.h >
#define PORT_NUM 777
inherit F_DBASE;
int run_server();
int do_server(int s);
int do_server1(int fd);
int do_quit(int fd);
int do_send_msg(int fd,string mess);
int do_who(int fd);
void create()
{
        set("name","grin");
        set("id","hehe");
        seteuid(getuid());
        run_server();
}
int run_server()
{
        int err,s;
        s = socket_create(STREAM,"create_callback","create_close");
        if (s < 0)
        {
                tell_object(this_player(),s + ": socket create error");
                return 1;
        }
        err = socket_bind(s,PORT_NUM);
        if (err!=EESUCCESS)
        {
                tell_object(this_player(),err + ": bind error.");
                return 1;
        }
        err = socket_listen(s,"listen_callback");
        if (err!=EESUCCESS)
        {
                tell_object(this_player(),err + ": listen error.");
                return 1;
        }
        return 1;
}
void listen_callback(int fd)
{
       
        int new_fd;
        if ( ( new_fd =
                socket_accept( fd, "in_read_callback", "in_write_callback" ) ) <
0 )
                return;
        do_server1(new_fd);
}
void in_read_callback(int fd,string str)
{
        string cmds,clas,yesno,whats;
        if (sscanf(str,"%s:::%s",clas,cmds) == 2)
                switch (clas) {
                        case "demand" :
                                switch (cmds) {
                                        case "who" : do_who(fd);break;
                                        //add some in here.
                                        default : socket_write(fd,"invaild deman
d");
                                }
                                break;
                        case "command" :
                                switch (cmds) {
                                        case "quit" : do_quit(fd);break;
                                        //add some in here.
                                        default : socket_write(fd,"invaild comma
nd");
                                }
                                break;
                        case "send" :
                                do_send_msg(fd,cmds);break;
                               
                        default : socket_write(fd,"invaild command.\n");
                                       
                }
        else if (sscanf(str,"%s---%s",yesno,whats) == 2)
                CHANNEL_D->do_channel(this_object(),"sys",whats);
        else if (str!="\r" && str!="\n" && str!="\r\n" && str!="\n\r") {
        socket_write(fd,"501 message has wrong format.\n");
        }
}
       
int do_who(int fd)
{
        object *objs;
        string users;
        int i;
       
        objs = users();
        if (socket_write(fd,"200 here is the online users list.\n") < 0)
//              CHANNLE_D->do_channel(this_object(),"sys","socket write error.")
;
        if (sizeof(objs)==0) return 0;
        users = objs[0]->query("name") + " ("+objs[0]->query("id") +")\n";
        for (i=1;i < sizeof(objs);i++)
        {
                if (!environment(objs[i])) continue;
                if (!interactive(objs[i])) continue;
                users = users + objs[i]->query("name") + " ("+objs[i]->query("id
") +")\n";

        }
        if (socket_write(fd,sizeof(objs)+" users:\n"+users) <0 )
//              CHANNLE_D->do_channel(this_object(),"sys","socket write error.")
;
        return 1;
}
int do_quit(int fd)
{
        if (socket_write(fd,"Good bye!") <0)
//      CHANNLE_D->do_channel(this_object(),"sys","socket write error.");
        socket_close(fd);
        return 1;
}
int do_send_msg(int fd,string mess)
{
        string who,msg;
        object ob;
        if (sscanf(mess,"%s %s",who,msg) != 2)
        {
                if (socket_write(fd,"513 you must supply the user name and messa
ge.") <0)
                return 1;
        }
        if (!find_player(who))
        {
                if (socket_write(fd,"514 you must supply the user name.") <0)
                return 1;
        }
        if (strlen(msg)>40)
        {
                if (socket_write(fd,"515 message is too long.") <0)    
                return 1;
        }
        ob = find_player(who);
        tell_object(ob,"有人从"+socket_address(fd)+"发送给您消息:\n"+
                        msg);
        socket_write(fd,"send completly.\n");
        return 1;
}
int do_server1(int s)
{
        int re;
        re = socket_write(s,"100 hello,welcome to MUDQQ server.\n");
        if (re != EESUCCESS && re != EECALLBACK) ;
//      CHANNLE_D->do_channel(this_object(),"sys","socket write error.");
        return 1;
}
呵呵,如果这个东东放到/adm/daemons下面的话,偶还可以把他做成一个黑客后门程序

偷到任何人的密码。HOHO。。。
如果命令过多的话,可以命令单独做成.c文件,然后在in_read_callback()里面来搜索
命令。
这样再做一个MUDOS都有可能了,呵呵。。。
第一次用LPC做SOCKET编程,呵呵,写得很幼稚,SORRY。。

 

尊重作者 转载请注明出处52mud.com

收藏 推荐 打印 | 录入:sbso | 阅读:
相关内容      
内容推送
52mud提供
一起回忆泥巴游戏QQ群68186072
52mud官方微信公众平台
热门评论