`
AvinDev
  • 浏览: 112990 次
社区版块
存档分类
最新评论

对Socket的{active, true}参数进行一些测试

阅读更多
以前不是很了解Erlang网络编程中流量控制,现在做一下笔记。

Erlang中Socket设置了{active, true}之后,接收到的网络消息会通过{tcp, Socket, Data}的格式主动发送给进程,这样做有个弊处就是没有做流量控制。要是有个客户端疯狂发包过来,服务器不做处理就等着堆溢出。
在《Programming Erlang》的14.2里面,介绍可以使用 {active, once} 来做控制。

{ok, Listen} = gen_tcp:listen(Port, [..,{active, once}...]),
{ok, Socket} = gen_tcp:accept(Listen),
loop(Socket).
  loop(Socket) ->
receive
  {tcp, Socket, Data} ->
    ... do something with the data ...
    %% when you're ready enable the next message
    inet:setopts(Sock, [{active, once}]),
    loop(Socket);
  {tcp_closed, Socket} ->
    ...
end.


不过锋爷认为这种做法会影响性能,因为每次接收信息都要调用一次 inet:setopts(Sock, [{active, once}]) 。

既然这样,那就先使用{active, true},如果判断到接收到的消息包太多,再改成 {active, once}。我写了个简单的代码:

listen_socket(Socket, Mode) ->
receive
	{tcp, Socket, Bin} ->
		process_req(Bin),
			{message_queue_len, MsgQueueSize} = erlang:process_info(self(), message_queue_len),
			if 
				(MsgQueueSize > 500) and (Mode =:= active_true) ->
					io:format("Queue size is ~p~n", [MsgQueueSize]),
					inet:setopts(Socket, [{active, once}]),
					listen_socket(Socket, active_once);
				(MsgQueueSize < 10) and (Mode =:= active_once) ->
					io:format("Queue size is ~p~n", [MsgQueueSize]),
					inet:setopts(Socket, [{active, true}]),
					listen_socket(Socket, active_true);
				true ->
					io:format("Queue size is ~p~n", [MsgQueueSize]),
					listen_socket(Socket, Mode)
            end;


判断当前进程消息队列的数量,大于500时被动接收,小于10时再次改为主动接收。
打开服务器后,客户端使用阻塞方式({active, false})连续来发送2000个消息包给服务器,很快服务器端的消息累计达到500以上,此时{active, once}被设置,数据包开始在系统底层堆积,很快就看到客户端的gen_tcp:send调用被阻塞,直到服务器设置{active, true}后,堆积的消息被加载到内存消息队列中,gen_tcp:send恢复正常发送。
可见当{active, once}被设置后,若消息队列中还有数据包,则系统底层的数据包会被堆积,起到了流量控制的作用。
分享到:
评论
4 楼 norain2050 2012-06-15  
AvinDev 写道
@ccppasm2
触发一次后,队列长度依然>500,则会再次调用
inet:setopts(Socket, [{active, once}]),  否则会调用
inet:setopts(Socket, [{active, true}]), 
因此都可以逐渐减少到<10


哈哈,版主解释的有点不对。当发现接收(控制)进程的信箱里的消息队列的长度大于500后,就改为半主动模式了(连接Socket,你就别再发给我消息了——Socket再转告操作系统——操作系统回复说“马上好,马上好,再接几个就让客户端阻塞”),此时接收进程里还有500多消息,因此,无须使用recv来从Socket要消息——因为接收进程自己的信箱里已经存有500多了,只需receive就成了。
  反复receive400到500多次后(每次无须调用inet:setopts),当信箱里的消息小于10了,才调用inet:setopts,告诉Socket可以继续转发消息了,Socket同时也告诉操作系统可以继续接收客户端的消息了(其实,此刻Socket里还保存了一些上次操作系统多接收的一点消息)。
3 楼 AvinDev 2008-10-24  
@ccppasm2
触发一次后,队列长度依然>500,则会再次调用
inet:setopts(Socket, [{active, once}]), 
否则会调用
inet:setopts(Socket, [{active, true}]), 
因此都可以逐渐减少到<10
2 楼 ccppasm2 2008-10-20  
>500后recieve只触发一次,如何再由500减少到<10?
1 楼 mryufeng 2008-05-22  
不会溢出。 inet:setopts {read_packets, N} 这个参数可以控制最大的未处理的包个数。

{read_packets, Integer}(UDP sockets)
    Sets the max number of UDP packets to read without intervention from the socket when data is available. When this many packets have been read and delivered to the destination process, new packets are not read until a new notification of available data has arrived. The default is 5, and if this parameter is set too high the system can become unresponsive due to UDP packet flooding.

相关推荐

    Delphi socket通信程序(源码,可运行)

    本程序是一个利用Delphi进行Socket通信的示例,包含了源代码,并且可以直接运行。 在Delphi中,Socket通信主要涉及两个关键组件:TServerSocket和TClientSocket。它们是VCL(Visual Component Library)库中的网络...

    delphi源码基础的Socket通信

    2. **客户端连接:** 在客户端程序中创建TClientSocket,设置Host和Port属性为服务器的信息,然后将Active设为True,客户端尝试连接。 3. **连接建立:** 当ServerSocket的OnAccept事件触发时,说明客户端已经连接...

    Delphi编写socket通讯服务端.rar

    4. 启动和停止服务器:在应用程序运行时,调用`TIdTCPServer.Active := True`启动服务器监听,`TIdTCPServer.Active := False`则会停止监听。 5. 安全性和错误处理:为了确保系统的稳定性和安全性,需要考虑SSL/TLS...

    这是Socket通信Demo,需要先启动服务端,然后打开客户端,连接后发送MMC中的内容

    Socket通信是一种基于TCP/IP协议族实现的网络通信方式,它允许两台计算机通过网络进行双向通信。在Delphi编程环境中,Socket通信常被用于构建服务器和客户端应用,以实现数据的实时交换。在这个Demo中,我们看到有...

    delphi Socket api简单的收发信息

    Server.Active := True; finally Server.Free; end; end; procedure TForm1.HandleServerExecute(AContext: TIdContext); var Data: string; begin Data := AContext.Connection.IOHandler.ReadLn; A...

    delphiTCP/IP socket编程自作实例

    本实例将深入探讨如何使用Delphi进行TCP/IP Socket通信,这对于构建分布式系统、实现客户端与服务器之间的数据交换具有极大的价值。 TCP/IP协议栈是互联网的核心,它定义了不同设备如何在网络中交换数据。TCP(传输...

    delphi socket通讯 demo

    在这个“delphi socket通讯 demo”中,我们将深入探讨如何使用Delphi 7中的TServerSocket和TClientSocket组件进行套接字通信。 首先,让我们了解什么是套接字(Socket)。套接字是操作系统提供的一个接口,允许程序...

    Delphi socket 通讯

    对于服务器端,设置 TServerSocket 的 Active 属性为 True 来启动监听。 4. **数据交换**: 通过 Socket 组件的 SendData 和 ReceiveData 方法来发送和接收数据。注意,发送的数据需要先转换成字符串或二进制格式。 5...

    delphi socket

    Server.Active := True; end; procedure TForm1.ServerExecute(AContext: TIdContext); var Data: string; begin Data := AContext.Connection.IOHandler.ReadLn(); ShowMessage('Received: ' + Data); ...

    delphi socket编程学习

    使用TIdTCPServer组件时,需要设置其Active属性为True,指定监听的Port,并绑定到IP地址。 3. **连接Socket**:客户端程序通过TIdTCPClient组件连接到服务器的指定端口。连接成功后,客户端和服务端就可以通过...

    socket在DELPHI中的应用实例

    在Delphi中,可以使用TServerSocket组件来创建服务器,将其Active属性设置为True以启动监听。TServerSocket组件会在指定的端口上等待连接请求。我们还需要一个TClientSocket组件来模拟客户端,用于建立与服务器的...

    Delphi的Socket客户端与服务端源码

    2. 开启监听,调用 `Active := True`。 3. 在 `OnExecute` 事件中,处理客户端的连接和数据交换。 4. 关闭连接,如果需要,可以在适当时候断开客户端连接。 在学习这个基础示例时,初学者会了解到如何设置Socket...

    delphi多线程socket服务器客户端

    - 绑定端口:设置TServerSocket的Active属性为True后,它会监听指定的Port,等待客户端连接。 - 连接事件:当有新的客户端连接时,触发OnAccept事件。此时,可以在事件处理函数中创建新的线程来处理该连接。 2. ...

    delphi socket通讯

    2. **启动服务器**:调用TIdTCPServer的Active属性设为True,服务器开始监听。在OnExecute事件中,我们可以编写代码来接收和发送数据。 3. **客户端连接**:在客户端,使用TIdTCPClient组件,设置Server属性为...

    套接字(Socket)编程的基本方法(供初学者参考)

     在编写程序时,首先要对TServerSocket(在服务器端)与TClientSocket(在客户端)进行实例化。对于TServerSocket的对象,主要设置其服务类型(ServerType)与端口(Port)的属性,然后编写“OnClientRead”事件...

    socket簡單的聊天程序

    - 连接到服务器,设置Active为True。 - 在OnConnect事件中,表示连接成功,可以开始发送和接收数据。 - 发送数据到服务器,可以通过TClientSocket的Write方法。 - 在OnDataAvailable事件中,读取服务器返回的...

    Delphi7_Socket_Server.rar

    在示例代码中,我们可能会看到TServerSocket的属性如`Active`被设置为True,使得服务器处于监听状态;`Port`属性则指定服务器监听的端口号,通常需要根据实际需求进行设定。 2. **TClientSocket组件**:对应于...

    delphi socket(ClientSocket,ServerSocket)简单实例

    - 异步模式:如果需要在用户界面线程之外处理网络操作,可以设置Socket组件的Active属性为True,并在OnExecute事件中处理数据读写。 - 数据格式:由于网络通信是字节流,因此需要定义数据的序列化和反序列化方式,如...

    dwsocket_socket_delphi7_

    本篇将深入探讨如何在Delphi 7环境中利用Socket进行服务端和客户端的开发。Delphi 7是一款经典的面向对象的 Pascal 编程工具,它内置了强大的VCL(Visual Component Library)框架,使得Socket编程变得相对简单。 ...

Global site tag (gtag.js) - Google Analytics