文字MUD游戏论坛-天下泥潭群英会-水泊梁山  

返回   文字MUD游戏论坛-天下泥潭群英会-水泊梁山 > 西游之旅 > 『 巫师天下 』

『 巫师天下 』 学习如何挂MUD,如何制作MUD。讨论如何管理好一个MUD,做好一个巫师。

发表新主题 回复
 
LinkBack 主题工具 主题评分 显示模式
旧 2011-12-03   #1
高级会员
级别:6 | 在线时长:109小时 | 升级还需:31小时级别:6 | 在线时长:109小时 | 升级还需:31小时级别:6 | 在线时长:109小时 | 升级还需:31小时
 
Odysseus 的头像
 
注册: 08年04月11日
来自: 盘丝洞
帖子: 311
声望力: 20
声望: 50 Odysseus 初领妙道
现金:29两梁山币
资产:1245两梁山币
致谢数: 0
获感谢文章数:0
获会员感谢数:0
用LPC做SERVER

//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。。
Odysseus 当前离线  
回复时引用此帖

发表新主题 回复

添加到书签


发帖规则
不可以发表主师
不可以回复帖子
不可以上传附件
不可以编辑自己的帖子

论坛启用 vB 代码
论坛启用 表情图标
论坛启用 [IMG] 代码
论坛禁用 HTML 代码
Trackbacks are 启用
Pingbacks are 启用
Refbacks are 启用



所有时间均为格林尼治时间 +9, 现在的时间是 09:42.


Powered by SPLS
版权所有 2001-2023 水泊梁山
皖ICP备05012024号

站长 fengyue

Content Relevant URLs by vBSEO 3.6.1