erlang的tcp批量客户端模板

tcp_client.erl

-module(tcp_client).

-export([start/2, stop/1]).

start({Ip,Port}, ClientNumber) ->
    io:format("~p,~p~n",[Ip,Port]),

    case tcp_client_handler_sup:start_link({Ip,Port}) of
        {ok, Pid} ->
            IndexList = lists:seq(1, ClientNumber),
            lists:foreach(
                fun(_Index) ->
                    tcp_client_handler_sup:start_child()
                end,
                IndexList
            ),
            {ok, Pid};
        _ ->
            {error, failed}
    end.

stop(_S) ->
    ok.

tcp_client_options.erl

-module(tcp_client_options).

-export([get_tcp_options/0, get_tcp_recv_timeout/0, get_tcp_conn_timeout/0]).

get_tcp_options() ->
    [
        {active, false},

        binary,
        {packet, 4},

        {nodelay,true},
        {send_timeout, 5*1000},
        {send_timeout_close, true},

        {reuseaddr, true},
        {keepalive, true},
        {packet_size, 4096}
    ].

get_tcp_recv_timeout() ->
    5*1000.

get_tcp_conn_timeout() ->
    5*1000.

tcp_client_handler_sup.erl

-module(tcp_client_handler_sup).
-behaviour(supervisor).

-export([start_link/1, start_child/0]).
-export([init/1]).

-define(SERVER, ?MODULE).

start_link({Ip,Port}) ->
    supervisor:start_link({local, ?SERVER}, ?MODULE, [{Ip,Port}]).

start_child() ->
    supervisor:start_child(?SERVER, []).

init([{Ip,Port}]) ->

    RestartMode = simple_one_for_one,
    MaxRestarts = 0,
    MaxSecondsBetweenRestarts = 1,

    RestartStrategy = {RestartMode, MaxRestarts, MaxSecondsBetweenRestarts},

    Restart = temporary,
    Shutdown = brutal_kill,
    Type = worker,

    Child = {
        tcp_client_handler,
        {tcp_client_handler, start_link, [{Ip,Port}]},
        Restart, Shutdown, Type,
        [tcp_client_handler]
    },

    Children = [Child],
    {ok, {RestartStrategy, Children}}.

tcp_client_handler.erl

-module(tcp_client_handler).
-behaviour(gen_server).

-export([start_link/1]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).
-export([loop_receive/2]).
-record(socket_info_record, {socket, ip, port}).

start_link({Ip,Port}) ->
    gen_server:start_link(?MODULE, [{Ip,Port}], []).

init([{Ip,Port}]) ->
    {ok, #socket_info_record{ip = Ip, port = Port}, 0}.

handle_call(Msg, _From, State) ->
    {reply, {ok, Msg}, State}.

%% 发数据包
handle_cast({send_socket_msg, Cmd, InfoBin}, State) ->
    send_socket_msg(Cmd, InfoBin,State);

%% 异步通知循环接收
handle_cast({loop_receive,ClientSocket}, State) ->
    loop_receive(ClientSocket,State);

handle_cast(stop, State) ->
    {stop, normal, State}.

handle_info({tcp_closed, _Socket}, #socket_info_record{ip = Addr} = StateData) ->
    HandlerMod = behavior_config:get_socket_handler_module(),
    HandlerMod:on_disconnected(Addr),
    {stop, normal, StateData};

handle_info(timeout, #socket_info_record{ip = Ip, port = Port} = State) ->
    case try_to_connect(Ip,Port,State) of
        {noreply, NewState} ->
            #socket_info_record{socket = Socket} = NewState,
            gen_server:cast(self(), {loop_receive,Socket}),
            {noreply, NewState};
        _ ->
            {stop, normal, State}
    end;

handle_info({delay, Module, CallBack, Args}, State) ->
    Module:CallBack(Args),
    {noreply, State};

handle_info(_Info, StateData) ->
    {noreply, StateData}.

terminate(_Reason, #socket_info_record{socket = Socket}) ->
    io:format("socket process terminated~n"),
    (catch gen_tcp:close(Socket)),
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

%% ---------------------------------------------------------------------------------------------------------------------
%% 尝试连接服务器
try_to_connect(Ip,Port,State) ->
    Options = tcp_client_options:get_tcp_options(),
    case gen_tcp:connect(Ip, Port, Options, tcp_client_options:get_tcp_conn_timeout() ) of
        {ok, Socket} ->
            {ok, {IP, _Port}} = inet:peername(Socket),

            io:format("~p连接~n",[IP]),

            {noreply, State#socket_info_record{socket = Socket}};
        {error, timeout}  ->
            {stop, normal, State}

    end.

%% 循环包处理函数
loop_receive(Socket, #socket_info_record{ip = Ip} = State) ->
    case gen_tcp:recv(Socket, 0, tcp_client_options:get_tcp_recv_timeout() ) of
        {ok, Data} ->
            io:format("收到远程数据~p~n",[Data]),

            loop_receive(Socket,State);
        {error, _Reason} ->
            io:format("连接~p断开~n",[Ip]),

            {stop, normal, State}
    end.

send_socket_msg(Cmd, InfoBin,#socket_info_record{socket = Socket} = State) ->
    Data = <<Cmd:16, InfoBin/binary>>,
    gen_tcp:send(Socket, Data),

    {noreply, State}.

tcp_send.erl

-module(tcp_send).

-export([send_data/3]).

send_data(Pid, Cmd, JsonBin) ->
    case erlang:is_pid(Pid) of
        true ->
            gen_server:cast(Pid, {send_socket_msg, Cmd, JsonBin});
        false ->
            io:format("socket pid invalid, ignore~n")
    end.
时间: 2024-07-30 10:04:01

erlang的tcp批量客户端模板的相关文章

基于TCP的客户端、服务器端socket编程

一.实验目的 理解tcp传输客户端服务器端通信流程 二.实验平台 MAC OS 三.实验内容 编写TCP服务器套接字程序,程序运行时服务器等待客户的连接,一旦连接成功,则显示客户的IP地址.端口号,并向客户端发送字符串. 四.实验原理 使用TCP套接字编程可以实现基于TCP/IP协议的面向连接的通信,它分为服务器端和客户端两部分,其主要实现过程如下 服务器端代码: 1 #include "iostream" 2 #include "netdb.h" 3 #inclu

MVC下的客户端模板技术

1.引言 在Web编程中,我们有时经常需要使用Ajax来访问服务端的接口,然后使用这些返回的数据(一般格式都是JSON)来展示客户端的相关信息.例如:在一个商品列表,我们点击某一样的商品,查看该商品的信息信息.这时通过指定的ID来获取商品详细信息后,我们很多时候都是讲HTML和JavaScript结合起来.通过构造HTML标签和JS的填充来展示相关的界面.这样大量的标签拼接,一来不容易维护,二来也导致在编码过程中容易出现错误.今天我给大家做一下客户端模板技术的简单介绍.希望可以通过这个技术在一定

linux 网络编程之最简单的tcp通信客户端

编写一个最为简单的tcp通信客户端.代码如下: #include <iostream> #include <cstring> using namespace std; #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <errno.h> int main() { /*创

黑马程序员——TCP的客户端与服务器端

/*  TCP 的客户端与服务器端 客户端: 1,建立Socket连接,制定服务器端的IP地址和端口号 2,获取流中的输入和输出流对象来操作数据 3.利用write方法将数据写出 4.关闭客户端 服务器端: 1.利用serverSocket指定端口与客户端建立连接 2.获取客户端对象,accept()方法 3.利用客户端对象获取输入和输出流对象来操作数据 4.提取数据, 5,一定时间后关闭客户端,服务器端一般不需要关闭 */ import java.io.*; import java.net.*

网络编程 UDP协议 TCP局域网客户端与服务端上传下载电影示例

UDP协议 (了解) 称之为数据包协议. 特点: 1) 不需要建立链接. 2) 不需要知道对方是否收到. 3) 数据不安全 4) 传输速度快 5)能支持并发 6) 不会粘包 7) 无需先启动服务端再启动客户端 优点: - 传输速度快 - 能支持并发 - 不会粘包 缺点: - 数据不安全, 容易丢失 应用场景: 早期的QQ聊天室. # server端 import socket # socket.SOCK_DGRAM ---> UPD协议 server = socket.socket(type=s

erlang的tcp服务器模板

网上抄来的,经过一系列调试,7788大概明白了,直接贴代码 tcp_server_app.erl -module(tcp_server_app). -behaviour(application). -export([start/2, stop/1]). -define(DEF_PORT, 2222). start(_Type, _Args) -> Opts = [ binary, {packet, 4}, {reuseaddr, true}, {keepalive, true}, {packet

Windows 下的最简单的TCP服务器客户端

他们是短连接的,服务器接受客户端之后,马上发送一个消息,发送完以后立即将客户端断开掉,然后继续等待下一个连接. 使用Winsocket2必须要引用到的头文件和需要包含到的链接库文件: #include <WinSock2.h> #pragma comment( lib, "ws2_32.lib" ) 以下代码是Winsocket2的系统初始化和关闭的封装代码. class WinSocketSystem { public: WinSocketSystem() { int i

【Echo】实验 -- 实现 C/C++下TCP, 服务器/客户端 通讯

本次实验利用TCP/IP, 语言环境为 C/C++ 利用套接字Socket编程,实现Server/CLient 之间简单的通讯. 结果应为类似所示: 下面贴上代码(参考参考...) Server 部分: 1 /* TCPServer.cpp - main */ 2 3 #include <stdlib.h> 4 #include <stdio.h> 5 #include <winsock2.h> 6 #include <time.h> 7 #include

socket编程:简单TCP服务器/客户端编程

其实对于socket:我们需要理解的是他提供了一种编程概念,利用socket就可以利用系统已经封装好的内部进行通信,我们只需要关注应用层方面的数据控制就OK了. 一. 套接字(socket) socket英文为插座的意思,也就是为用户提供了一个接入某个链路的接口.而在计算机网络中,一个IP地址标识唯一一台主机,而一个端口号标识着主机中唯一一个应用进程,因此"IP+端口号"就可以称之为socket. 两个主机的进程之间要通信,就可以各自建立一个socket,其实可以看做各自提供出来一个&