首页 > 作文

Java面试Socket编程常用参数设置源码问题分析

更新时间:2023-04-06 02:45:08 阅读: 评论:0

引导语

socket 中文翻译叫套接字,可能很多工作四五年的同学都没有用过这个 api,但只要用到这个 api 时,必然是在重要的工程的核心代码处。

大家平时基本都在用开源的各种 rpc 框架,比如说 dubbo、grpc、spring cloud 等等,很少需要手写网络调用,以下三小节可以帮助大家补充这块的内容,当你真正需要的时候,可以作为手册示例。

本文和《rversocket 源码及面试题》一文主要说 socket 和 rversocket 的源码,《工作实战:socket 结合线程池的使用》这章主要说两个 api 在实际工作中如何落地。

1、socket 整体结构

socket 的结构非常简单,socket 就像一个壳一样,将套接字初始化、创建连接等各种操作包装了一下,其底层实现都是 socketimpl 实现的,socket 本身的业务逻辑非常简单。

socket 的属性不多,有套接字的状态,socketimpl,读写的状态等等,源码如下图:

套接字的状态变更都是有对应操作方法的,比如套接字新建(createimpl 方法)后,状态就会更改成 created = true,连接(connect)之后,状态更改成 connected = true 等等。

2、初始化

socket 的构造器比较多,可以分成两大类:

指定代理类型(proxy)创建套节点,一共有三种类型为:direct(直连)、http(http、ftp 高级协议的代理)、socks(socks 代理),三种不同的代码方式对应的 socketimpl 不同,分别是:plainsocketimpl、httpconnectsocketimpl、sockssocketimpl,除了类型之外 proxy 还指定了地址和端口;

默认 sockssocketimpl 创建,并且需要在构造器中传入地址和端口,源码如下:

这里的 address 可以是 ip 地址或者域名,比如说 127.0.0.1 或者 www.wenhe.com。

我们一起看一下这个构造器调用的 this 底层构造器的源码:

从源码中可以看出:

在构造 socket 的时候,你可以选择 tcp 或 udp,默认是 tcp;如果构造 socket 时,传入地址和端口,那么在构造的时候,就会尝试在此地址和端口上创建套接字;socket 的无参构造器只会初始化 sockssocketimpl,并不会和当前地址端口绑定,需要我们手动的调用 connect 方法,才能使用当前地址和端口;socket 我们可以理解成网络沟通的语言层次的抽象,底层网络创建、连接和关闭,仍然是 tcp 或 udp 本身网络协议指定的标准,socket 只是使用 java 语言做了一层封装,从而让我们更方便地使用。

3、connect 连接服务端

connect 方法主要用于 socket 客户端连接上服务端,如果底层是 tcp 层协议的话,就是通过三次握手和服务端建立连接,为客户端和服务端之间的通信做好准备,底层源码如下:

connect 方法要求有两个入参,第一个入参是 socketaddress,表示服务端的地址,我们可以使用 inetsocketaddress 进行初始化,比如:new inetsocketaddress(“www.wenhe.com”, 2000)。

第二入参是超时时间的意思(单位毫秒),表示客户端连接服务端的最大等待时间,如果超过当前等待时间,仍然没有成功建立连接,抛 sockettimeoutexception 异常,如果是 0 的话,表示无限等待。

4、socket 常用设置参数

socket 的常用设置参数在 socketoptions 类中都可以找到,接下来我们来一一分析下,以下理解大多来自类注释和网络。

4.1、ttcpnodelay

此方法是用来设置 tcp_nodelay 属性的,属性的注释是这样的:此设置仅仅对 tcp 生效,主要为了禁止使用 nagle 算法,true 表示禁止使用,fal 表示使用,默认是 fal。

对于 nagle 算法,我们引用维基百科上的解释:

纳格算法是以减少数据包发送量来增进 [tcp/ip] 网络的性能,它由约翰·纳格任职于ford aerospace时命名。

纳格的文件[注 1]描述了他所谓的“小数据包问题”-某个应用程序不断地提交小单位的数据,且某些常只占1字节大小。因为tcp数据包具有40字节的标头信息(tcp与ipv4各占20字节),这导致了41字节大小的数据包只有1字节的可用信息,造成庞大的浪费。这种状况常常发生于telnet工作阶段-大部分的键盘操作会产生1字节的数据并马上提交。更糟的是,在慢速的网络连线下,这类的数据包会大量地在同一时点传输,造成壅塞碰撞。

纳格算法的工作方式是合并(coalescing)一定数量的输出数据后一次提交。特别的是,只要有已提交的数据包尚未确认,发送者会持续缓冲数据包,直到累积一定数量的数据才提交。

总结算法开启关闭的场景:

如果 nagle 算法关闭,对于小数据包,比如一次鼠标移动,点击,客户端都会立马和服务端交互,实时响应度非常高,但频繁的通信却很占用不少网络资源;如果 nagle 算法开启,算法会自动合并小数据包,等到达到一定大小(mss)后,才会和服务端交互,优点是减少了通信次数,缺点是实时响应度会低一些。

socket 创建时,默认是开启 nagle 算法的,可以根据实时性要求来选择是否关闭 nagle 算法。

4.2、tsolinger

tsolinger 方法主要用来设置 so_linger 属性值的。

注释上大概是这个意思:在我们调用 clo 方法时,默认是直接返回的,但如果给 so_linger 赋值,就会阻塞 clo 方法,在 so_linger 时间内,等待通信双方发送数据,如果时间过了,还未结束,将发送 tcp rst 强制关闭 tcp 。

我们看一下 tsolinger 源码:

4.3、toobinline

toobinline 方法主要使用设置 so_oobinline 属性。

注释上说:挽回老公如果希望接受 tcp urgent data(tcp 紧急数据)的话,可以开启该选项,默认该选项是关闭的,我们可以通过 socket#ndurgentdata 方法来发送紧急数据。

查询了很多资料,都建议尽可能的去避免设置该值,禁止使用 tcp 紧急数据。

4.4、tsotimeout

tsotimeout 方法主要是用来设置 so_ti六一儿童节礼物清单meout 属性的。

注释上说:用来设置阻塞操作的超时时间,阻塞她在丛中笑全诗操作主要有:

rversocket.accept() 服务器等待客户端的连接;socketinputstream.read() 客户端或服务端读取输入超时;datagramsocket.receive()。

我们必须在必须在阻塞操作之前设置该选项, 如果时间到了,操作仍然在阻塞,会抛出 interruptedioexception 异常(socket 会抛出 sockettimeoutexception 异常,不同的套接字抛出的异常可能不同)。

对于 socket 来说,超时时间如果设置成 0,表示没有超时时间,阻塞时会无限等待。

4.5、tndbuffersize

tndbuffersize 方法主要用于设置 so_sndbuf晚会串词 属性的,入参是 int 类型,表示设置发送端(输出端)的缓冲区的大小,单位是字节。

入参 size 必须大于 0,否则会抛出 illegalargumentexception 异常。

一般我们都是采取默认的,如果值设置太小,很有可能导致网络交互过于频繁,如果值设置太大,那么交互变少,实时性就会变低。

4.6、treceivebuffersize

treceivebuffersize 方法主要用来设置 so_rcvbuf 属性的,入参是 int 类型,表示设置接收端的缓冲区的大小,单位是字节。

入参 size 必须大于 0,否则会抛出 illegalargumentexception 异常。

一般来说,在套接字建立连接之后,我们可以随意修改窗口大小,但是当窗口大小大于 64k 时,需要注意:

必须在 socket 连接客户端之前设置缓冲值;必须在 rversocket 绑定本地地址之前设置缓冲值。

4.7、tkeepalive

tkeepalive 方法主要用来设置 so_keepalive 属性,主要是用来探测服务端的套接字是否还是存活状态,默认设置是 fal,不会触发这个量变和质变功能。

如果 so_keepalive 开启的话,tcp 自动触发功能:如果两小时内,客户端和服务端的套接字之间没有任何通信,tcp 会自动发送 keepalive 探测给对方,对方必须响应这个探测(假设是客户端发送给服务端),预测有三种情况:

服务端使用预期的 ack 回复,说明一切正常;服务端回复 rst,表示服务端处于死机或者重启状态,终止连接;没有得到服务端的响应(会尝试多次),表示套接字已经关闭了。

4.8、treuaddress

treuaddress 方法主要用来设置 so_reuaddr 属性,入参是布尔值,默认是 fal。

套接字在关闭之后,会等待一段时间之后才会真正的关闭,如果此时有新的套接字前来绑定同样的地址和端口时,如果 treuaddress 为 true 的话,就可以绑定成功,否则绑定失败。

5、总结

如果平时一直在做业务代码,socket 可能用到的很少,但面试问到网络协议时,或者以后有机会做做中间件的时候,就会有大概率会接触到 socket,所以多学学,作为知识储备也蛮好的。

以上就是java编程socket结构常用参数设置源码及面试题的详细内容,更多关于java编程socket结构常用参数面试的资料请关注www.887551.com其它相关文章!

本文发布于:2023-04-06 02:45:06,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/fb426e391dc747c4312e2aebd3ce7f81.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:Java面试Socket编程常用参数设置源码问题分析.doc

本文 PDF 下载地址:Java面试Socket编程常用参数设置源码问题分析.pdf

下一篇:返回列表
标签:服务端   方法   算法   数据包
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图