`
solingye
  • 浏览: 20054 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

IRC程序

阅读更多
IRC协议:因特网在线聊天协议(IRC)可以分散的运行多台机器,从而实现internet的远程会议。IRC协议利用基本的TCP/IP网络协议系统开发。但是它并没有要求TCP/IP是唯一的运行环境。IRC是一种文本协议,它仅要求用户有一个简单端口程序能与服务器连接。

IRC的一种典型配置包括:服务器形成一个供客户机(或其它服务器)连接、实现所需信息的发送/多路复用技术等功能的信道,服务器作为 IRC 中枢,提供与客户机连接的信道从而实现相互间的聊天;此外它也提供与服务器连接的信道,从而形成一个 IRC 网络。IRC 服务器需要唯一网络配置生成树,每一个服务器充当一个中心代码服务于生成树所看到的其它网络部分。】

为了维持 IRC 网络中的合理秩序,需要一种特殊类型的客户机(操作员)以实现基本的网络维护功能。所谓 IRC 信道指一个命名的包含一个或多个用户的小組,送给这个信道的信息,每一个组内的用户均可收到。

IRC允许两个客户之间的相互通信,一个用户对多个其他用户、以及用户对服务器和服务器对服务器。IRC协议为大多数网络消息及聊天系统提供了技术基础。

协议结构:
IRC是一种具有很多命令的文本协议,主要命令有:
用户〈用户名〉〈主机名〉〈服务器名〉〈真实名〉:在连接初使用,详细说明新用户的用户名、主机名、服务器名及真实名。
通过〈口令〉:在设置“连接口令”时使用。
昵称〈昵称〉〈跳转〉:给用户一个昵称或更换以前的昵称。
服务器〈服务器名〉〈跳转〉〈信息〉:告诉服务器连接的另一个终端是服务器。
进入〈用户〉〈口令〉:请求获得操作权。
停止〈停止消息〉:用户会话以停止消息结束。
服务器停止〈服务器〉〈注释〉:停止和终结服务器提示。
连接〈频道〉:客户机开始收听特别频道。
主题〈频道〉:改换或检查频道。
名字〈频道〉:列出所有的昵称使其他任何信道上的用户都可以看到。
目录〈信道〉:列出信道及其主题。
删除〈信道〉〈用户〉〈注释〉:强制性地从信道上删除用户 。



类IRC程序:
五个组件:
1.用户界面组件:用于接收到的消息显示出来的GUI窗口组件。也负责发送消息,它发出的消息会发送到聊天客户端组件。
2.聊天客户端:负责管理来自聊天窗口的消息,然后将他们转发至当前群组的群控制器。它也负责接收来自群控制器的消息,并将这些消息再转发给聊天窗口。
3.群控制器:负责管理单个聊天组,如果群控制器接收到一个消息,它会将这条消息广播到组中的所有的成员。它还会持续跟踪新加入和离开的成员,并在所有组成员都退出该群时自行注销。
4.聊天服务器:负责持续跟踪所有的群控制器,当有一个新的成员试图加入一个群组时,聊天服务器才会工作,无论是有一个,还是有多个群组控制器,聊天服务器都是单进程的。
5.中间人:负责管理系统之间的数据传输,它屏蔽了两台机器之间的底层套接字接口。使我们无须关心底层的通信基础结构的细节问题。


聊天客户端:
-module(chat_client).

-import(io_widget, 
	[get_state/1, insert_str/2, set_prompt/2, set_state/2, 
	 set_title/2, set_handler/2, update_state/3]).

-export([start/0, test/0, connect/5]).

//启动客户端,
start() -> 
    connect("localhost", 2223, "AsDT67aQ", "general", "joe").


test() ->
    connect("localhost", 2223, "AsDT67aQ", "general", "joe"),
    connect("localhost", 2223, "AsDT67aQ", "general", "jane"),
    connect("localhost", 2223, "AsDT67aQ", "general", "jim"),
    connect("localhost", 2223, "AsDT67aQ", "general", "sue").
	   
//创建handler/5的并行进程。
connect(Host, Port, HostPsw, Group, Nick) ->
    spawn(fun() -> handler(Host, Port, HostPsw, Group, Nick) end).

//把自己转换为系统进程
//创建一个输入输出窗口组件,并设置
//创建连接进程(这个进程会尝试连接服务器)
//最后在disconnected/2函数内等待一个连接事件				 
handler(Host, Port, HostPsw, Group, Nick) ->
    process_flag(trap_exit, true),
    Widget = io_widget:start(self()),
    set_title(Widget, Nick),
    set_state(Widget, Nick),
    set_prompt(Widget, [Nick, " > "]),
    set_handler(Widget, fun parse_command/1),
    start_connector(Host, Port, HostPsw),    
    disconnected(Widget, Group, Nick).


//等待接收一个从服务器返回的{connected,MM}的响应。
disconnected(Widget, Group, Nick) ->
    receive
	{connected, MM} ->
	    insert_str(Widget, "connected to server\nsending data\n"),
	    lib_chan_mm:send(MM, {login, Group, Nick}),
	    wait_login_response(Widget, MM);
	{Widget, destroyed} ->
	    exit(died);
	{status, S} ->
	    insert_str(Widget, to_str(S)),
	    disconnected(Widget, Group, Nick);
	Other ->
	    io:format("chat_client disconnected unexpected:~p~n",[Other]),
	    disconnected(Widget, Group, Nick)
    end.

wait_login_response(Widget, MM) ->
    receive
	{chan, MM, ack} ->
	    active(Widget, MM);
	Other ->
	    io:format("chat_client login unexpected:~p~n",[Other]),
	    wait_login_response(Widget, MM)
    end. 

//负责窗口组件和群组之间的消息传递,并监视与群组的连接。
active(Widget, MM) ->
     receive
	 {Widget, Nick, Str} ->
	     lib_chan_mm:send(MM, {relay, Nick, Str}),
	     active(Widget, MM);
	 {chan, MM, {msg, From, Pid, Str}} ->
	     insert_str(Widget, [From,"@",pid_to_list(Pid)," ", Str, "\n"]),
	     active(Widget, MM);
	 {'EXIT',Widget,windowDestroyed} ->
	     lib_chan_mm:close(MM);
	 {close, MM} ->
	     exit(serverDied);
	 Other ->
	     io:format("chat_client active unexpected:~p~n",[Other]),
	     active(Widget, MM)
     end. 


//定期的尝试与IRC服务器连接,try_to_connect不断循环。每两秒尝试连接一下服务器,如//果无法连接,就发送一个状态消息给聊天客户端
start_connector(Host, Port, Pwd) ->
    S = self(),
    spawn_link(fun() -> try_to_connect(S, Host, Port, Pwd) end).

try_to_connect(Parent, Host, Port, Pwd) ->
    %% Parent is the Pid of the process that spawned this process
    case lib_chan:connect(Host, Port, chat, Pwd, []) of
	{error, _Why} ->
	    Parent ! {status, {cannot, connect, Host, Port}},
	    sleep(2000),
	    try_to_connect(Parent, Host, Port, Pwd);
	{ok, MM} ->
	    lib_chan_mm:controller(MM, Parent),
	    Parent ! {connected, MM},
	    exit(connectorFinished)
    end.

//让程序等待T毫秒
sleep(T) ->
    receive
    after T -> true
    end.
    
to_str(Term) ->
    io_lib:format("~p~n",[Term]).

parse_command(Str) -> skip_to_gt(Str).

skip_to_gt(">" ++ T) -> T;
skip_to_gt([_|T])    -> skip_to_gt(T);
skip_to_gt([])       -> exit("no >").


lin_chan的配置:
{port, 2223}.
{service, chat, password,"AsDT67aQ",mfa,mod_chat_controller,start,[]}.


聊天控制器:
//只接收两种消息,当客户端连上来时,它会收到一个消息,然后把它转发给聊天服务器,
//与之相反的情况是,如果会话因为某种原因而终止,它会收到一个退出消息,然后通知聊//天服务器客户端已经退出
-module(mod_chat_controller).
-export([start/3]).
-import(lib_chan_mm, [send/2]).

start(MM, _, _) ->
    process_flag(trap_exit, true),
    io:format("mod_chat_controller off we go ...~p~n",[MM]),
    loop(MM).

loop(MM) ->
     receive
	 {chan, MM, Msg} ->
	     chat_server ! {mm, MM, Msg},
	     loop(MM);
	 {'EXIT', MM, _Why} ->
	     chat_server ! {mm_closed, MM};
	 Other ->
	     io:format("mod_chat_controller unexpected message =~p (MM=~p)~n",
		       [Other, MM]),
	     loop(MM)
    end. 


聊天服务器:
-module(chat_server).
-import(lib_chan_mm, [send/2, controller/2]).
-import(lists, [delete/2, foreach/2, map/2, member/2,reverse/2]).

-compile(export_all).

//注册进程chat_server,并且在内部启动lib_chan
start() ->
    start_server(),
    lib_chan:start_server("chat.conf").

start_server() ->
    register(chat_server, 
	     spawn(fun() ->
			   process_flag(trap_exit, true),
			   Val= (catch server_loop([])),
			   io:format("Server terminated with:~p~n",[Val])
		   end)).

//等待一个{login,Group,Nick}的消息,这个消息来自通道为PID的中间人,如果存在与这个//群组对应的群组控制器,那么就想群组控制器发送登录消息,否则,开启一个新的群组控制//器。
server_loop(L) ->
    receive
	{mm, Channel, {login, Group, Nick}} ->
	    case lookup(Group, L) of
		{ok, Pid} ->
		    Pid ! {login, Channel, Nick},
		    server_loop(L);
		error ->
		    Pid = spawn_link(fun() ->
					     chat_group:start(Channel, Nick) 
				     end),
		    server_loop([{Group,Pid}|L])
	    end;
	{mm_closed, _} ->
	    server_loop(L); 
	{'EXIT', Pid, allGone} ->
	    L1 = remove_group(Pid, L),
	    server_loop(L1);
	Msg ->
	    io:format("Server received Msg=~p~n",
		      [Msg]),
	    server_loop(L)
    end.



lookup(G, [{G,Pid}|_]) -> {ok, Pid};
lookup(G, [_|T])       -> lookup(G, T);
lookup(_,[])           -> error.

remove_group(Pid, [{G,Pid}|T]) -> io:format("~p removed~n",[G]), T;
remove_group(Pid, [H|T])       -> [H|remove_group(Pid, T)];
remove_group(_, [])            -> [].


聊天群组(群组管理器):
-module(chat_group).
-import(lib_chan_mm, [send/2, controller/2]).
-import(lists, [foreach/2, reverse/2]).

-export([start/2]).

start(C, Nick) ->
    process_flag(trap_exit, true),
    controller(C, self()),
    send(C, ack),
    self() ! {chan, C, {relay, Nick, "I'm starting the group"}},
    group_controller([{C,Nick}]).



delete(Pid, [{Pid,Nick}|T], L) -> {Nick, reverse(T, L)};
delete(Pid, [H|T], L)          -> delete(Pid, T, [H|L]);
delete(_, [], L)               -> {"????", L}.


//参数为L的列表,元素形如{Pid,Nick},存放了用户昵称和中间的Pid.
group_controller([]) ->
    exit(allGone);
group_controller(L) ->
    receive
	{chan, C, {relay, Nick, Str}} ->
	    foreach(fun({Pid,_}) -> send(Pid, {msg,Nick,C,Str}) end, L),
	    group_controller(L);
	{login, C, Nick} ->
	    controller(C, self()),
	    send(C, ack),
	    self() ! {chan, C, {relay, Nick, "I'm joining the group"}},
	    group_controller([{C,Nick}|L]);
	{chan_closed, C} ->
	    {Nick, L1} = delete(C, L, []),
	    self() ! {chan, C, {relay, Nick, "I'm leaving the group"}},
	    group_controller(L1);
	Any ->
	    io:format("group controller received Msg=~p~n", [Any]),
	    group_controller(L)
    end.


输入输出窗口(聊天用户界面):
-module(io_widget).

-export([get_state/1,
	 start/1, test/0, 
	 set_handler/2, 
	 set_prompt/2,
	 set_state/2,
	 set_title/2, insert_str/2, update_state/3]).

//创建一个新的输入输出窗口,返回一个可以用于与窗口组件进行交互的PID,
//当用户在输入框输入一条消息时,运行这个函数的进程就会收到形如{PID,State,Parse}的//消息,State是一个可以由用户设置的状态变量,Parse是输入的字符串用用户定义的解析//器解析之后的结果。
start(Pid) -> 
    gs:start(),
    spawn_link(fun() -> widget(Pid) end).

get_state(Pid)          -> rpc(Pid, get_state).

//设置窗体组件的标题
set_title(Pid, Str)     -> Pid ! {title, Str}.

//设置窗体组件的解析器为Fun.当用户在窗口中输入一行字符串时,窗口组件会发送//{PID,State,Parse}这条消息,Parse是经过窗体组件的解析器解析之后的字符串。当用户//关闭组件时,在窗口组件摧毁之间会发送{Pid,destoryed}这条消息.
set_handler(Pid, Fun)   -> Pid ! {handler, Fun}.

set_prompt(Pid, Str)    -> Pid ! {prompt, Str}.

//设置窗体组件的状态
set_state(Pid, State)   -> Pid ! {state, State}.

insert_str(Pid, Str)    -> Pid ! {insert, Str}.
update_state(Pid, N, X) -> Pid ! {updateState, N, X}. 

rpc(Pid, Q) ->    
    Pid ! {self(), Q},
    receive
	{Pid, R} ->
	    R
    end.

widget(Pid) ->
    Size = [{width,500},{height,200}],
    Win = gs:window(gs:start(),
		    [{map,true},{configure,true},{title,"window"}|Size]),
    gs:frame(packer, Win,[{packer_x, [{stretch,1,500}]},
			  {packer_y, [{stretch,10,120,100},
				      {stretch,1,15,15}]}]),
    gs:create(editor,editor,packer, [{pack_x,1},{pack_y,1},{vscroll,right}]),
    gs:create(entry, entry, packer, [{pack_x,1},{pack_y,2},{keypress,true}]),
    gs:config(packer, Size),
    Prompt = " > ",
    State = nil,
    gs:config(entry, {insert,{0,Prompt}}),
    loop(Win, Pid, Prompt, State, fun parse/1). 

loop(Win, Pid, Prompt, State, Parse) ->   
    receive
	{From, get_state} ->
	    From ! {self(), State},
	    loop(Win, Pid, Prompt, State, Parse);
	{handler, Fun} ->
	    loop(Win, Pid, Prompt, State, Fun);
	{prompt, Str} ->
	    %% this clobbers the line being input ...
	    %% this could be fixed - hint
	    gs:config(entry, {delete,{0,last}}),
	    gs:config(entry, {insert,{0,Str}}),
	    loop(Win, Pid, Str, State, Parse);
	{state, S} ->
	    loop(Win, Pid, Prompt, S, Parse);
	{title, Str} ->
	    gs:config(Win, [{title, Str}]),
	    loop(Win, Pid, Prompt, State, Parse);
	{insert, Str} ->
	    gs:config(editor, {insert,{'end',Str}}),
	    scroll_to_show_last_line(),
	    loop(Win, Pid, Prompt, State, Parse);
	{updateState, N, X} ->
	    io:format("setelemtn N=~p X=~p Satte=~p~n",[N,X,State]),
	    State1 = setelement(N, State, X),
	    loop(Win, Pid, Prompt, State1, Parse);
	{gs,_,destroy,_,_} ->
	    io:format("Destroyed~n",[]),
	    exit(windowDestroyed);
	{gs, entry,keypress,_,['Return'|_]} ->
	    Text = gs:read(entry, text),
	    %% io:format("Read:~p~n",[Text]),
	    gs:config(entry, {delete,{0,last}}),
	    gs:config(entry, {insert,{0,Prompt}}),
	    try Parse(Text) of
		Term ->
		    Pid ! {self(), State, Term}
	    catch
		_:_ ->
		    self() ! {insert, "** bad input**\n** /h for help\n"}
	    end,
	    loop(Win, Pid, Prompt, State, Parse);
	{gs,_,configure,[],[W,H,_,_]} ->
	    gs:config(packer, [{width,W},{height,H}]),
	    loop(Win, Pid, Prompt, State, Parse);
	{gs, entry,keypress,_,_} ->
	    loop(Win, Pid, Prompt, State, Parse);
	Any ->
	    io:format("Discarded:~p~n",[Any]),
	    loop(Win, Pid, Prompt, State, Parse)
    end.

scroll_to_show_last_line() ->
    Size       = gs:read(editor, size),
    Height     = gs:read(editor, height),
    CharHeight = gs:read(editor, char_height),
    TopRow     = Size - Height/CharHeight,
    if  TopRow > 0 -> gs:config(editor, {vscrollpos, TopRow});
	true       -> gs:config(editor, {vscrollpos, 0})
    end.

test() ->
    spawn(fun() -> test1() end).

test1() ->
    W = io_widget:start(self()),
    io_widget:set_title(W, "Test window"),
    loop(W).

loop(W) ->
    receive
	{W, {str, Str}} ->
	    Str1 = Str ++ "\n",
	    io_widget:insert_str(W, Str1),
	    loop(W)
    end.

//默认的解析器。
parse(Str) ->
    {str, Str}.
分享到:
评论

相关推荐

    irc-code.rar_irc

    【描述】:“Irc程序的一套源代码,和大家一起分享。希望大家能够完善” 这段描述指出,该资源是一个开源项目,目的是为了促进开发者之间的交流与合作。作者希望通过共享这些源代码,鼓励其他开发者参与进来,共同...

    IRC的客户端程序的源程序(229KB)

    标题中的“IRC的客户端程序的源程序”表明这是一个关于Internet Relay Chat(IRC)客户端软件的源代码包。IRC是一种实时的、基于文本的聊天系统,允许用户通过频道进行多对多交流,或进行一对一的私人对话。源代码是...

    sdbot.rar典型的基于irc僵尸程序源码

    【sdbot.rar】是一个包含典型基于IRC(Internet Relay Chat)僵尸网络程序源码的压缩文件。IRC僵尸网络是一种恶意软件技术,攻击者利用这种技术控制大量被感染的计算机(称为“肉鸡”),形成一个网络,用于进行...

    irc客户端程序 (80KB)...

    标题中的“irc客户端程序”指的是Internet Relay Chat (IRC) 的客户端软件,这是一种允许用户通过互联网进行实时文本聊天的协议。这个程序是用VB(Visual Basic)编写的,VB是一种流行的微软开发的编程语言,尤其...

    IRC聊天室客户端程序C++代码

    本项目提供了一个使用C++编写的IRC聊天室客户端程序,对于想要学习网络编程,尤其是TCP/IP通信和多线程处理的开发者来说,这是一个非常有价值的资源。 1. IRC协议基础: IRC协议定义了客户端如何连接到服务器、...

    基于IRC的sdbot僵尸程序源码

    sdbot僵尸程序,基于IRC协议的僵尸网络程序 VC环境C语言开发,通过测试。

    irc客户端程序 (80KB)

    标题中的“irc客户端程序 (80KB)”指的是一个基于IRC(Internet Relay Chat)协议的轻量级客户端软件,它的大小约为80KB,这在早期的互联网时代是常见的大小,表明该程序可能具有一定的历史背景。 IRC是一种实时的...

    IRCserver基于IRC的通信实现

    1. **主程序**:启动服务器,初始化网络监听和资源管理。 2. **网络模块**:处理TCP连接,读写数据,可能包括异步I/O或多线程处理。 3. **命令处理器**:解析接收到的IRC命令,调用相应的处理函数。 4. **会话管理**...

    ABB喷涂机器人IRC5P通过Profinet通讯启动程序号关联程序启动流程,ABB喷涂机器人IRC5P通讯关联程序号启动,profinet ,核心关键词:ABB喷涂机器人; IRC5P通讯; 程序号

    ABB喷涂机器人IRC5P通过Profinet通讯启动程序号关联程序启动流程是一套高效、精确的自动化解决方案。Profinet作为工业自动化领域广泛应用的工业以太网标准,它的使用使得机器人与生产系统之间的通讯更为高效、稳定。...

    IRC_receiver.rar_IRC matlab_IRC receiver_irc by matlab_irc干扰_干扰消

    CoMP场景下,基于PMI的IRC干扰消除算法的仿真程序,算法可以参考论文“Interference Mitigation Based on Enhanced Interference PMI Notification”

    irc_client.zip_irc_irc client

    这个压缩包包含了一系列源代码文件,用于创建一个能够连接到IRC服务器并进行实时聊天的客户端程序。 【描述】"VC编写的IRC客户端演示" 提示我们这个项目是用VC++来实现的,可能是一个教学或示例性的项目,旨在展示...

    ABB喷涂机器人IRC5P通过Profinet通讯启动程序号关联程序启动流程,ABB喷涂机器人IRC5P通讯启动与程序号启动流程研究:Profinet通讯协议应用解析,ABB喷涂机器人IRC5P通讯关

    ABB喷涂机器人IRC5P通过Profinet通讯启动程序号关联程序的启动流程,是现代工业自动化技术发展的一个缩影。它不仅展示了ABB在机器人技术领域的深厚积累,也体现了Profinet通讯协议在工业自动化中的广泛应用前景。...

    IRC协议(rfc1459)

    客户端是用户与IRC网络交互的接口,可以是任何能够连接到服务器并通过TCP/IP发送和接收数据的应用程序。客户端通常分为图形界面和命令行两种类型。 - **操作员**:操作员是一种特殊类型的用户,拥有额外权限来管理...

    mirc.zip_irc_irc bot

    在这个场景中,"bot" 指的是一种自动化程序,它连接到 IRC 服务器并执行预定义的任务,如欢迎新用户、管理频道、转发消息等。 描述中的 "irc server use dieu khien bot" 提到了使用 IRC 机器人进行控制。这可能...

    IRC.zip_IRC server_IRCserver_irc_sircd.c_简单IRC实现

    通过阅读和分析`sircd.c`,我们可以学习到如何将IRC协议转化为实际的程序代码,这有助于理解网络编程和协议实现的基本概念。 总结,这个“IRC.zip”提供的资源是一个学习和研究IRC协议的好机会,特别是对于那些对...

    操作员手册—IRC5与FlexPendant.pdf

    在FlexPendant的使用介绍中,手册先给出FlexPendant和IRC5控制器的简介,然后引导如何在系统启动时进行微动控制,使用RAPID程序和输入输出端口操作。用户还能够执行备份和恢复操作,授予RobotStudio访问权限,进行...

    IRC-Client-Sources.rar_IRC delphi_delphi irc_delphi irc client_i

    总之,这个压缩包提供的资源对于学习和理解如何在Delphi中使用TIdIRC组件来构建IRC客户端应用程序非常有价值。通过深入研究这些源代码和项目文件,开发者可以掌握IRC协议的实现细节,以及Delphi中组件驱动的编程模式...

    IRC客户端演示.rar_client irc_irc

    压缩包内的"www.pudn.com.txt"可能是关于IRC客户端使用教程的文本文件,而"IRC客户端演示"可能是一个实际的客户端应用程序或源代码示例,供学习者研究和实践。 总的来说,这个压缩包为那些想深入了解或开发IRC...

    IRC的Matrix网关:从您最喜欢的IRC客户端连接到Matr.zip

    它允许用户通过不同的应用程序和服务进行无缝的信息交流。而IRC(Internet Relay Chat)则是一种较老但仍然广泛使用的实时聊天系统,尤其在技术社区中颇受欢迎。将Matrix与IRC连接起来的网关使得这两种通信方式能够...

Global site tag (gtag.js) - Google Analytics