1.只接收一个连接然后自动关闭的服务端代码

 1 -module(socket_server).
 2
 3 -export([start_nano_server/0]).
 4
 5 start_nano_server() ->
 6     % 监听来自端口2345上的连接,消息打包规则{packet, 4} -> 每个应用程序都是从一个4字节长的头部开始
 7     % gen_tcp:listen -> {ok, ListenSocket} | {error, Reason}, ListenSocket为监听套接字
 8     {ok, ListenSocket} = gen_tcp:listen(2345, [binary, {packet, 4},
 9                                         {reuseaddr, true},
10                                         {active, true}]),
11     % gen_tcp:accept(Listensocket)调用时,程序会暂停并等待一个连接
12     % 当一个新的连接建立起来时会返回变量Socket,该变量绑定到新建连接的套接字上
13     % 通过Socket套接字,服务器就可以和发起连接的客户机进行通信
14     {ok, Socket} = gen_tcp:accept(ListenSocket),
15     % 关闭监听套接字,此后服务器不会继续处于监听状态,也无法建立新的连接,但并不影响已经建立的连接套接字
16     % 只是阻止新连接的建立
17     gen_tcp:close(ListenSocket),
18     loop(Socket).
19
20 loop(Socket) ->
21     receive
22         {tcp, Socket, Bin} ->
23             io:format("Server received binary = ~p~n", [Bin]),
24             Str = binary_to_term(Bin),  % 对接收数据解码(反整编)
25             io:format("Server(unpacked) ~p~n", [Str]),
26             Reply = lib_misc:string2value(Str),     % 对回应数据进行编码(整编)
27             io:format("Server replying = ~p~n", [Reply]),
28             % send(Socket, Packet) -> ok | {error, Reason}, Packet -> iodata()
29             gen_tcp:send(Socket, term_to_binary(Reply)),
30             loop(Socket);
31         {tcp_closed, Socket} ->
32             io:format("Server socket closed~n")
33     end.

2.顺序型服务器

 1 %% 顺序型服务器
 2 -module(socket_server_order).
 3
 4 -export([start_nano_server/0]).
 5
 6 start_nano_server() ->
 7     % 监听来自端口2345上的连接,消息打包规则{packet, 4} -> 每个应用程序都是从一个4字节长的头部开始
 8     % gen_tcp:listen -> {ok, ListenSocket} | {error, Reason}, Listen为监听套接字
 9     {ok, ListenSocket} = gen_tcp:listen(2345, [binary, {packet, 4},
10                                         {reuseaddr, true},
11                                         {active, true}]),
12     req_loop(ListenSocket).
13
14 req_loop(ListenSocket) ->
15     {ok, Socket} = gen_tcp:accept(ListenSocket),
16     loop(Socket),
17     req_loop(ListenSocket).
18
19 loop(Socket) ->
20     receive
21         {tcp, Socket, Bin} ->
22             io:format("Server received binary = ~p~n", [Bin]),
23             Str = binary_to_term(Bin),
24             io:format("Server(unpacked) ~p~n", [Str]),
25             Reply = lib_misc:string2value(Str),
26             io:format("Server replying = ~p~n", [Reply]),
27             gen_tcp:send(Socket, term_to_binary(Reply)),
28             loop(Socket);
29         {tcp_closed, Socket} ->
30             io:format("Server socket closed~n")
31     end.

3.并发型服务器

 1 %% 并发型服务器
 2 -module(socket_server_order).
 3
 4 -export([start_nano_server/0]).
 5
 6 start_nano_server() ->
 7     % 监听来自端口2345上的连接,消息打包规则{packet, 4} -> 每个应用程序都是从一个4字节长的头部开始
 8     % gen_tcp:listen -> {ok, ListenSocket} | {error, Reason}, Listen为监听套接字
 9     {ok, ListenSocket} = gen_tcp:listen(2345, [binary, {packet, 4},
10                                         {reuseaddr, true},
11                                         {active, true}]),
12     spawn(fun() -> par_connect(ListenSocket) end).
13
14 par_connect(ListenSocket) ->
15     {ok, Socket} = gen_tcp:accept(ListenSocket),
16     spawn(fun() -> par_connect(ListenSocket) end),
17     loop(Socket).
18
19 loop(Socket) ->
20     receive
21         {tcp, Socket, Bin} ->
22             io:format("Server received binary = ~p~n", [Bin]),
23             Str = binary_to_term(Bin),
24             io:format("Server(unpacked) ~p~n", [Str]),
25             Reply = lib_misc:string2value(Str),
26             io:format("Server replying = ~p~n", [Reply]),
27             gen_tcp:send(Socket, term_to_binary(Reply)),
28             loop(Socket);
29         {tcp_closed, Socket} ->
30             io:format("Server socket closed~n")
31     end.

4.客户端代码

 1 -module(socket_client).
 2
 3 -export([nano_client_eval/1]).
 4
 5 nano_client_eval(Str) ->
 6     {ok, Socket} = gen_tcp:connect("localhost", 2345,
 7                                     [binary, {packet, 4}]),
 8     ok = gen_tcp:send(Socket, term_to_binary(Str)),
 9     receive
10         {tcp, Socket, Bin} ->
11             io:format("Client received binary = ~p~n", [Bin]),
12             Val = binary_to_term(Bin),
13             io:format("Client result = ~p~n", [Val]),
14             gen_tcp:close(Socket)
15     end.

5.lib_misc模块

1 -module(lib_misc).
2
3 -export([string2value/1]).
4
5 string2value(L) -> string2value(L, []).
6 string2value([], N)    -> list_to_tuple(lists:reverse(N));
7 string2value([H|T], N) -> string2value(T, [H|N]).

6.测试

  6.1只接收一个连接然后自动关闭的服务端代码测试

  6.2顺序型服务器测试

 

 6.3并发型测试

ps:顺序型服务器相对并发型服务器的区别在于:顺序型服务器忙于服务一个现存的连接时,如果又有新的客户机尝试连接服务器,那么这个连接就会在服务器排队,直到服务器完成对现有的服务为止,如果等待队列中的连接数目超过了监听套接字的能力,那么这个连接就会被拒绝,而并发型服务器则不会有该问题

转载于:https://www.cnblogs.com/huangxiaoyi/p/5709588.html

一个简单的TCP服务器相关推荐

  1. 笨办法学C 练习45:一个简单的TCP/IP客户端

    练习45:一个简单的TCP/IP客户端 原文:Exercise 45: A Simple TCP/IP Client 译者:飞龙 我打算使用RingBuffer来创建一个非常简单的小型网络测试工具,叫 ...

  2. [C# 网络编程系列]专题十二:实现一个简单的FTP服务器

    引言: 休息一个国庆节后好久没有更新文章了,主要是刚开始休息完心态还没有调整过来的, 现在差不多进入状态了, 所以继续和大家分享下网络编程的知识,在本专题中将和大家分享如何自己实现一个简单的FTP服务 ...

  3. 3-4:一个简单的HTTP服务器

    文章目录 HTTP服务器 HTTP服务器 我们使用浏览器请求某一个网页时,浏览器会向相应的服务器发送请求,服务器得到请求后会将报文传送回来,然后浏览器解析,就形成了我们所看见到的网页 这里我们可以写一 ...

  4. 用python写一个简单的web服务器

    人生苦短,我用python 简洁高效,这才是理想的语言啊 分享一点python的学习经验-----如何用python写一个简单的web服务器 首先,我们需要简单地了解一下网络通信协议,这里用白话介绍一 ...

  5. 通过python 构建一个简单的聊天服务器

    构建一个 Python 聊天服务器 一个简单的聊天服务器 现在您已经了解了 Python 中基本的网络 API:接下来可以在一个简单的应用程序中应用这些知识了.在本节中,将构建一个简单的聊天服务器.使 ...

  6. libev实现简单的tcp服务器

    本文将介绍如何用libev创建一个简单的tcp echo server服务器,实现一个简单的异步(asynchronous)tcp server的功能,该server接收客户端连接,然后读取已连接客户 ...

  7. 一个简单的RTMP服务器实现 --- RTMP实现要点

    #PS:要转载请注明出处,本人版权所有 #PS:这个只是 < 我自己 >理解,如果和你的 #原则相冲突,请谅解,勿喷 背景 参考前置文章:<一个简单的RTMP服务器实现 - RTMP ...

  8. Mina、Netty、Twisted一起学(一):实现简单的TCP服务器

    MINA.Netty.Twisted为什么放在一起学习?首先,不妨先分别看一下它们官方网站对其的介绍: MINA: Apache MINA is a network application frame ...

  9. 专题十二:实现一个简单的FTP服务器

    引言: 在本专题中将和大家分享如何自己实现一个简单的FTP服务器.在我们平时的上网过程中,一般都是使用FTP的客户端来对商家提供的服务器进行访问(上传.下载文件),例如我们经常用到微软的SkyDriv ...

最新文章

  1. 【maven】初识maven
  2. Ambari在离线环境中安装Hadoop集群
  3. CSS媒体查询 @media
  4. solaris下常见文件压缩/解压方式简单小结—待续中
  5. 从零入门 FreeRTOS操作系统之信号量
  6. 反骨仔的 2016 年度全文目录索引
  7. 视觉注意力机制(上)
  8. android之微信分享图片
  9. mysql置信度支持度,关于支持度和置信度的说明
  10. 每日编程-20170326
  11. 基于嵌入式系统的gnash最小库依赖关系
  12. Intent在Activity间的传值
  13. 从cocos2d-x到unity看游戏研发、设计中一些要点
  14. 电脑重装系统苹果电脑开不了机的原因分析
  15. 手把手系列--STM32H750移植FreeRTOS(二)--优化编译速度
  16. 自旋锁(spin lock)学习
  17. 【GIS小案例】点聚合效果的实现
  18. spinnaker-简介
  19. Java编程思想——复用类
  20. cad打开卡死_cad2010打开就卡死怎么回事_教你解决cad2010打开就卡死问题

热门文章

  1. POJ 3087 Shuffle'm Up 线性同余,暴力 难度:2
  2. iptables复习记忆
  3. C++ enum 枚举
  4. typeof null的返回值是什么?_数据类型与typeof
  5. shell的执行流控制
  6. html中纯js互斥按钮,JS如何实现checkbox互斥功能
  7. 云原生乘风者联合征文活动——说出你和「阿里云云原生」的故事
  8. Cube 技术解读 | 支付宝新一代动态化技术架构与选型综述
  9. 智能搜索推荐一体化营收增长解决方案
  10. 实时计算 Flink 版总体介绍