Socket  Programming Considerations

写Socket程序的时候需要注意设置下面的timeout,避免对方没有响应的时候,导致Socket程序挂起或等待时间过长

1.1         Accept Timeout

Accept timeout 仅对ServerSocket有用。ServerSocket 使用accept()方法来监听客户端Socket的连接。默认,ServerSocket.accept() 方法会一直阻塞直到有客户端来连接。通常,我们不需要设置accept timeout.

但有时候特殊情况,还是要考虑设置accept timeout.

比如: 程序A给程序B发了一个JMS消息,然后程序A启动一个Socket Server,想通过socket等待接收程序B的返回消息。如果不设置accept timeout, 并且程序B因为某些原因一直不能连接Socket Server,最终会导致程序A挂起。

Accept Timeout可以这样设置:

ServerSocket serverSocket = new ServerSocket(5555);

serverSocket.setSoTimeout(5000); // in milliseconds

while (true) {

Socket socket = serverSocket.accept();

}

1.2         Connect Timeout

当Client端连接Server端的时候,可以指定Connect Timeout

如果没有指定,会使用操作系统的默认值:

OS

Default TCP timeout

BSD

75 seconds

Linux

189 seconds

Solaris

225 seconds

Windows XP

21 seconds

Connect Timeout可以这样设置:

SocketAddress socketAddress = new InetSocketAddress(host, port);

socket = new Socket();

socket.connect(socketAddress, connectTimeout);

 

1.3         Receive Timeout

当socket从另一方接收数据时,可以设置Receive Timeout

默认没有timeout,socket会一直阻塞直到有数据可读取。

Receive Timeout可以这样设置:

Socket socket = new Socket(host, port);

socket.setSoTimeout(timeout);

 

1.4         Send Timeout

Send Timeout是socket给另一方发送数据时使用的。

不过Java里没有办法设置Send Timeout.

当然,socket发送数据的时候,会首先发送到本机OS的一个buffer内。一般只要一次发送的数据不是很大,即使对方挂起或暂时不能接收数据,也不会导致发送方挂起。

2.1       Socket ack (acknowledgement)

Socket ack是指当socket接收到数据之后,发送一个ack字符串(比如$ACK)给socket发送方。这样,socket发送方可以根据是否收到了ack判断对方是否收到了数据。

Socket ack是显示的在应用程序中加入的一种通讯协议。如果不使用ack,在socket通讯中,可能会丢失数据。

比如,socket client要连续的给socket server发送100条消息。如果我们在server收到第50条消息的时候,强行kill了server。那么查询client端发送的log,可能client端成功发送了51条。只有当client端发送第52条消息的时候才遇到异常。这样第51条消息就丢失了。

所以为了确保数据传输的准确性,我们可以引入ack协议。有时我们不仅要确保server不但收到了数据,而且还要保证server成功处理了数据。这时,可以等server成功处理完数据之后,再给client发ack。

2.2       Socket Keep Alive

Socket连接像数据库连接一样,属于重量型资源。如果我们频繁的创建socket、发送/接收数据、关闭socket,那么会有很大一部分时间浪费在socket的创建和关闭上。

所以,如果我们经常需要与同一个socket地址发送/接收数据时,应该考虑只创建一次socket,然后一直使用这个socket对象发送/接收数据。

2.3       Heartbeat

通常,我们会设置socket的receive timeout。这样,如果我们一直打开着socket (keep alive), 而很长时间又没有数据通讯,socket接收方就会timeout,最终导致打开的连接坏掉。

如果很长时间没有数据通讯,防火墙或代理服务器也可能会关闭打开的socket连接。

所以为了保证打开的socket连接一直可用,如果一段时间没有数据进行通讯(或指定一个时间间隔),我们可以显示的发送一个heartbeat消息(比如: $HRT)给对方,从而保证连接不会被异常关闭。

2.4       Socket Close

每一个socket对象会持有一个socket descriptor (其实就是file descriptor),操作系统对于socket descriptor有一个最大限制。因此当socket不再使用时,一定要记得关闭,即使socket连接失败或出现异常,只要socket对象不为null,一定要记得关闭。

下面图显示了,当socket关闭时,socket的状态变化(socket状态可以通过netstat命令查看)。更详细的解释,可以google一下。

当主动一方调用close(先调用close)时的状态变化:

ESTABLISHED -> FIN_WAIT_1-> FIN_WAIT_2 -> TIME_WAIT -> CLOSED

当被动一方调用close(后调用close)时的状态变化:

ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED

通常,TIME_WAIT 是正常状态,过一段时间(2MSL, 1到4分钟)就会自动消失.

我们需要特别注意CLOSE_WAIT 状态:

1.如果很长时间才消失,表明socket server处理太慢,很多client已经连接到server,发送完数据并close了。

2.如果一直也不消失,表明有socket没有正常close (对方已经close了)

2.5   SO_REUSEADDR Option

当socket主动调用close的时候,从上面可以知道,它最终会进入TIME_WAIT 状态,需要过1到4分钟,才能完全close。

当socket处于TIME_WAIT 状态时,它仍然占用正在使用的IP/PORT。这样,如果我们的程序(比如socket server)使用了一个固定的IP/PORT,当socket处于TIME_WAIT 状态时,程序将不能立即重启,会出现端口占用错误。

Socket提供了一个setReuseAddress()方法,可以设置当socket处于TIME_WAIT状态时,是否允许其它进程绑定这个端口。

如果我们正在开发socket server,一定要记得调用ServerSocket.setReuseAddress(true).

Client socket也有这个方法,而且有时可能需要指明client连接server时所使用的本地IP/PORT(一般不用指明,系统会随机选择一个PORT)。但实际测试,在client socket上设置这个方法在Windows和Solaris下并不起作用。当socket处于TIME_WAIT 状态时,重启client仍然出现端口占用错误。上网搜索了很长时间,很多人都碰到了这个问题,可能是操作系统底层socket实现问题。因为测试使用C语言开发的socket client,同样也有这个错误。有人说LINUX下好用,还有就是可以尝试修改tcp_time_wait_interval来减小TIME_WAIT等待时间

转载于:https://www.cnblogs.com/kevinGao/archive/2011/11/04/2236169.html

Socket基础知识分享相关推荐

  1. oracle基础知识文档,Oracle 基础知识分享PPT

    因测试组需求,所以把Oracle基础知识整理成了PPT,并讲解了一下(PPT无风格,简约派吐舌头). Oracle 是以高级结构化查询语言(SQL)为基础的大型关系数据库,通俗地讲它是用方便逻辑管理的 ...

  2. Turtle库与Time库基础知识分享(详细)

    Turtle库与Time库基础知识分享(详细) 认识turtle库: turtle库是turtle绘图体系的Python实现,是标准库之一 标准库:随解释器操作系统中的模块直接安装到解释器中的并且可以 ...

  3. php socket 基础知识

    ◆ Socket 基础 PHP使用Berkley的 socket库来创建它的连接.socket只不过是一个数据结构.你使用这个socket数据结构去开始一个客户端和服务器之间的会话.这个服务器是一 直 ...

  4. socket基础知识以及各种使用场景

    一.socket的基础知识 1.1socket的使用场景以及分类 socket本来也是用于本地进程间通信的,后来有了TCP/IP协议族的加入,才能实现跨主机通信. socket是一个函数,我们可以指定 ...

  5. oracle对查询结果求和_oracle基础知识分享

    原文链接:https://page.om.qq.com/page/OO2PXCD6VZ6CVqLqjpU6uShg0 以下是本人整理的ORACLE学习的一些基本的语法知识,如有不对的地方,望大家批评指 ...

  6. 电工基础知识分享(四):图文并茂,史上最全万用表使用手册

    哈喽,大家好!我们又见面了,前几期我分享了一些最基本的电工知识.今天,我们就来好好学习一下,万用表的正确使用方法. 万用表原本是属于电工的一种专业测量工具,但现在出现的电子万用表操作简单.寿命长.价格 ...

  7. 天猫店铺基础知识分享

    天猫平台作为发展得已经非常成熟的电商平台,也推出了一些专属功能方便卖家运营店铺.天猫灯塔指标是一项网店运营综合辅助功能,作为卖家也需要进行相应的了解,熟悉相关知识.那么,下面我们就来跟大家分享一些相关 ...

  8. 子网规划与组网实验_【干货】从0到1,“大型WLAN组网”基础知识分享~

    点击蓝字 关注我们 目前,大多数企业办公环境同时使用有线和无线网络来支撑业务.办公区在提供有线网口的同时,也采用全Wi-Fi覆盖,办公环境更为开放和智能.未来,企业云桌面办公.智真会议.4K视频等大带 ...

  9. docker 基础知识分享ppt

    给团队做的docker基础分享ppt, 见下面的附件. https://files.cnblogs.com/files/harrychinese/docker_intro.pptx 转载于:https ...

最新文章

  1. Python----Day1
  2. 【蓝桥杯】基础练习 十进制转十六进制
  3. [链接]开方检验原理
  4. 计算机科学必读书籍_5篇关于数据科学家的产品分类必读文章
  5. Oracle数据库是如何执行SQL的
  6. CENTOS 指定 yum 阿里云 源
  7. 录音转换成mp3格式
  8. 2020苏州大学计算机考研经验总结博
  9. Synonyms 中文近义词工具包 -- 支持文本对齐,推荐算法,相似度计算,语义偏移,关键字提取,概念提取,自动摘要,搜索引擎等
  10. Java 数据填充到word模板中
  11. 洛谷P1338 末日的传说
  12. 小鑫の日常系列故事(七)——小纸条
  13. 极光推送报错time_to_live value should be a non-negative integertime_to_live value should be a non-negativ
  14. stm32f407zgt6的pdr_on引脚怎么接
  15. 100个人检测一个,最少需要多少试管
  16. Matlab坐标系绘制
  17. java+mysql+javaweb网上购物系统
  18. 意迷观看欧冠决赛慌乱踩踏 公共安防再次升级
  19. mysql数据库data目录下文件说明
  20. 编辑MyEclipse的模板

热门文章

  1. 超级*** 08鬼斧神工
  2. sql查询条件为空的另类写法o( ̄▽ ̄)d
  3. Makefile-filter和filter-out
  4. HD-ACM算法专攻系列(9)——大菲波数
  5. AngularJS中的表单验证机制
  6. Java版 数字金额大写转换
  7. 设置元素浮动的几种方式
  8. 关于Windowsn 7因验证未通过被视为“非正版”出现“黑屏”的应急处理预案
  9. Linux shell命令提示符
  10. 巩固shell基础知识