- 浏览: 669855 次
- 性别:
- 来自: 广州
-
文章分类
最新评论
本文为原创,如需转载,请注明作者和出处,谢谢!
上一篇:Java网络编程从入门到精通(28):获取ServerSocket信息的方法及FTP原理
ServerSocket类有以下三个选项:
1. SO_TIMEOUT: 设置accept方法的超时时间。
2. SO_REUSEADDR:设置服务端同一个端口是否可以多次绑定。
3. SO_RECBUF:设置接收缓冲区的大小。
一、SO_TIMEOUT选项
可以通过SeverSocket类的两个方法(setSoTimeout和getSoTimeout)来设置和获得SO_TIMEOUT选项的值,这两个方法的定义如下:
publicsynchronizedintgetSoTimeout()throwsIOException
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 11"><meta name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!--[if gte mso 9]><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} @font-face {font-family:""@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ @page {} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman";} </style> <![endif]-->
setSoTimeout方法的timeout参数表示accept方法的超时时间,单位是毫秒。在通常情况下,ServerSocket类的accept方法在等待客户端请求时处于无限等待状态。如HTTP服务器在没有用户访问网页时会一直等待用户的请求。一般不需要对服务端设置等待客户端请求超时,但在某些特殊情况下,服务端规定客户端必须在一定时间内向服务端发出请求,这时就要设置等待客户端请求超时,也就是accept方法的超时时间。当设置客户端请求超时后,accept方法在等待超时时间后抛出一个SocketTimeoutException异常。下面的代码演示了如何设置和获得SO_TIMEOUT选项的值,超时时间通过命令行参数方式传入AcceptTimeout。
importjava.net.*;
publicclassAcceptTimeout
{
publicstaticvoidmain(String[]args)throwsException
{
if(args.length==0)
return;
ServerSocketserverSocket=newServerSocket(1234);
inttimeout=Integer.parseInt(args[0]);
serverSocket.setSoTimeout(Integer.parseInt(args[0]));
System.out.println((timeout>0)?"accept方法将在"
+serverSocket.getSoTimeout()+"毫秒后抛出异常!":"accept方法永远阻塞!");;
serverSocket.accept();
}
}
执行下面的命令:
运行结果:
Exceptioninthread"main"java.net.SocketTimeoutException:Accepttimedout
atjava.net.PlainSocketImpl.socketAccept(NativeMethod)
atjava.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
atjava.net.ServerSocket.implAccept(ServerSocket.java:450)
atjava.net.ServerSocket.accept(ServerSocket.java:421)
atchapter5.AcceptTimeout.main(AcceptTimeout.java:16)
setSoTimeout方法可以在ServerSocket对象绑定端口之前调用,也以在绑定端口之后调用。如下面的代码也是正确的:
serverSocket.setSoTimeout(3000);
serverSocket.bind(newInetSocketAddress(1234));
二、SO_REUSEADDR选项
SO_REUSEADDR选项决定了一个端口是否可以被绑定多次。可以通过SeverSocket类的两个方法(setReuseAddres和getReuseAddress)来设置和获得SO_TIMEOUT选项的值,这两个方法的定义如下:
publicbooleangetReuseAddress()throwsSocketException
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 11"><meta name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!--[if gte mso 9]><![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} @font-face {font-family:""@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ @page {} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman";} </style> <![endif]-->
在大多数操作系统中都不允许一个端口被多次绑定。如果一个ServerSocket对象绑定了已经被占用的端口,那么ServerSocket的构造方法或bind方法就会抛出一个BindException异常。
Java提供这个选项的主要目的是为了防止由于频繁绑定释放一个固定端口而使系统无法正常工作。当ServerSocket对象关闭后,如果ServerSocket对象中仍然有未处理的数据,那么它所绑定的端口可能在一段时间内不会被释放。这就会造成其他的ServerSocket对象无法绑定这个端口。在设置这个选项时,如果某个端口是第一次被绑定,无需调用setReuseAddress方法,而再次绑定这个端口时,必须使用setReuseAddress方法将这个选项设为true。而且这个方法必须在调用bind方法之前调用。下面的代码演示了如何设置和获得这个选项的值:
importjava.net.*;
publicclassTestReuseAddr1
{
publicstaticvoidmain(String[]args)throwsException
{
ServerSocketserverSocket1=newServerSocket(1234);
System.out.println(serverSocket1.getReuseAddress());
ServerSocketserverSocket2=newServerSocket();
serverSocket2.setReuseAddress(true);
serverSocket2.bind(newInetSocketAddress(1234));
ServerSocketserverSocket3=newServerSocket();
serverSocket3.setReuseAddress(true);
serverSocket3.bind(newInetSocketAddress(1234));
}
}
运行结果:false
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 11"><meta name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml>
Normal
0
7.8 磅
0
2
false
false
false
MicrosoftInternetExplorer4
</xml><![endif]--><!--[if gte mso 9]><![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:""@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
font-size:10.5pt;
font-family:"Times New Roman";}
/* Page Definitions */
@page
{}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.Section1
{page:Section1;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.0pt;
font-family:"Times New Roman";}
</style>
<![endif]-->
在上面代码中第一次绑定端口1234,因此,serverSocket1对象无需设置SO_REUSEADDR选项(这个选项在大多数操作系统上的默认值是false)。而serverSocket2和serverSocket3并不是第一次绑定端口1234,因此,必须设置这两个对象的SO_REUSEADDR值为true。在设置SO_REUSEADDR选项时要注意,必须在ServerSocket对象绑定端口之前设置这个选项。
也许有的读者可能有这样的疑问。如果多个ServerSocket对象同时绑定到一个端口上,那么当客户端向这个端口发出请求时,该由哪个ServerSocket对象来接收客户端请求呢?在给出答案之前,让我们先看看下面的代码的输出结果是什么。
importjava.net.*;
publicclassTestReuseAddr2extendsThread
{
Strings;
publicvoidrun()
{
try
{
ServerSocketserverSocket=newServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(newInetSocketAddress(1234));
Socketsocket=serverSocket.accept();
System.out.println(s+":"+socket);
socket.close();
serverSocket.close();
}
catch(Exceptione)
{
}
}
publicTestReuseAddr2(Strings)
{
this.s=s;
}
publicstaticvoidmain(String[]args)
{
for(inti=1;i<=5;i++)
newTestReuseAddr2("ServerSocket"+i).start();
}
}
执行下面的命令:
连续执行5次下面的命令:
执行结果:
ServerSocket3:Socket[addr=/127.0.0.1,port=11725,localport=1234]
ServerSocket5:Socket[addr=/127.0.0.1,port=11726,localport=1234]
ServerSocket2:Socket[addr=/127.0.0.1,port=11727,localport=1234]
ServerSocket4:Socket[addr=/127.0.0.1,port=11728,localport=1234]
上面的运行结果只是一种可能,如果多次按着上面的步骤操作,可能得到不同的运行结果。由此可以断定,当多个ServerSocket对象同时绑定一个端口时,系统会随机选择一个ServerSocket对象来接收客户端请求。但要注意,这个接收客户端请求的ServerSocket对象必须关闭(如019行如示),才能轮到其他的ServerSocket对象接收客户端请求。如果不关闭这个ServerSocket对象,那么其他的ServerSocket对象将永远无法接收客户端请求。读者可以将
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 11"><meta name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml>
Normal
0
7.8 磅
0
2
false
false
false
MicrosoftInternetExplorer4
</xml><![endif]--><!--[if gte mso 9]><![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:""@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
font-size:10.5pt;
font-family:"Times New Roman";}
/* Page Definitions */
@page
{}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.Section1
{page:Section1;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.0pt;
font-family:"Times New Roman";}
</style>
<![endif]-->serverSocket.close()去掉,再执行上面操作步骤,看看会有什么结果。
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 11"><meta name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml>
Normal
0
7.8 磅
0
2
false
false
false
MicrosoftInternetExplorer4
</xml><![endif]--><!--[if gte mso 9]><![endif]--><!--[if !mso]>
<style>
st1":*{behavior:url(#ieooui) }
</style>
<![endif]--><style>
<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;}
@font-face
{font-family:""@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
font-size:10.5pt;
font-family:"Times New Roman";}
/* Page Definitions */
@page
{}
@page Section1
{size:612.0pt 792.0pt;
margin:72.0pt 90.0pt 72.0pt 90.0pt;}
div.Section1
{page:Section1;}
-->
</style><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{
mso-style-parent:"";
font-size:10.0pt;
font-family:"Times New Roman";}
</style>
<![endif]-->三、SO_RCVBUF选项
可以通过SeverSocket类的两个方法(setReceiveBufferSize和getReceiveBufferSize)来设置和获得SO_RCVBUF选项的值,这两个方法的定义如下:
publicsynchronizedintgetReceiveBufferSize()throwsSocketException
importjava.net.*;
publicclassTestReceiveBufferSize
{
publicstaticvoidmain(String[]args)throwsException
{
ServerSocketserverSocket=newServerSocket(1234);
serverSocket.setReceiveBufferSize(2048);//将接收缓冲区设为2K
while(true)
{
Socketsocket=serverSocket.accept();
//如果客户端请求使用的是本地IP地址,重新将Socket对象的接
//收缓冲区设为1K
if(socket.getInetAddress().isLoopbackAddress())
socket.setReceiveBufferSize(1024);
System.out.println("serverSocket:"
+serverSocket.getReceiveBufferSize());
System.out.println("socket:"+socket.getReceiveBufferSize());
socket.close();
}
}
}
执行如下命令:
telnetlocalhost1234
telnet192.168.18.1001234
socket:2048
serverSocket:2048
socket:1024
serverSocket:2048
socket:2048
从上面的运行结果可以看出,在执行telnet localhost 1234命令后,由于localhost是本地地址,因此程序通过将Socket对象的接收缓冲区设为1024,而在执行其他两条命令后,由于192.168.18.100不是本机地址,所以Socket对象的接收缓冲区仍然保留着serverSocket的值:2048。因此,我们可以得出一个结论,设置ServerSocket对象的接收缓冲区就相当于设置了所有从accept返回的Socket对象的接收缓冲区,只要不单独对某个Socket对象重新设置,这些Socket对象的接收缓冲区就会都保留这个值。
无论在ServerSocket对象绑定到端口之前还是之后设置SO_RCVBUF选项都有效,但如果要设置大于64K的接收缓冲区时,就必须在ServerSocket对象绑定端口之前设置SO_RCVBUF选项。如下面的代码将接收缓冲区的大小设为100K。
serverSocket.setReceiveBufferSize(100*1024);//将接收缓冲区的大小设为100K。
serverSocket.bind(newInetSocketAddress(1234));
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="ProgId" content="Word.Document"><meta name="Generator" content="Microsoft Word 11"><meta name="Originator" content="Microsoft Word 11"><link rel="File-List" href="file:///C:%5CDOCUME%7E1%5CADMINI%7E1%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml"><!--[if gte mso 9]><xml> Normal 0 7.8 磅 0 2 false false false MicrosoftInternetExplorer4 </xml><![endif]--><!--[if gte mso 9]><![endif]--><!--[if !mso]> <style> st1":*{behavior:url(#ieooui) } </style> <![endif]--><style> <!-- /* Font Definitions */ @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1;} @font-face {font-family:""@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; font-size:10.5pt; font-family:"Times New Roman";} /* Page Definitions */ @page {} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt;} div.Section1 {page:Section1;} --> </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable { mso-style-parent:""; font-size:10.0pt; font-family:"Times New Roman";} </style> <![endif]-->
一般情况下,并不需要设置这个选项,它的默认值(一般为8K)足可以满足大多数情况。但有时为了适应特殊的需要,必须更改接收缓冲区的值。如在一些网络游戏中,需要实时地向服务器传送各种动作、指令信息。这就需要将接收缓冲区设小一点。这样可以在一定程度上增加游戏客户端的灵敏度。如果需要传送大量的数据,如HTTP、FTP等协议。这就需要较大的接收缓冲区。
四、设置ServerSocket的性能偏好
在Java SE5.0及以上版本中为ServerSocket类增加了一个setPerformancePreferences方法。这个和方法和Socket类中的setPerformancePreferences的作用一样,用来设置连接时间、延迟和带宽的相对重要性。setPerformancePerferences方法的定义如下:
下一篇:Java网络编程从入门到精通(30):定制accept方法
国内最棒的Google Android技术社区(eoeandroid),欢迎访问!
《银河系列原创教程》发布
《Java Web开发速学宝典》出版,欢迎定购
相关推荐
### JAVA网络编程从入门到精通知识点详解 #### 一、Internet地址概述 互联网中的每一台设备都需要有一个唯一的标识符——IP地址。当前广泛使用的IPv4地址由四个字节组成,而未来的趋势是采用16个字节的IPv6地址。 ...
chromedriver-win64-136.0.7059.0.zip
python学习一些项目和资源
python学习资源
python学习资源
python学习教程
python学习教程
【毕业设计】java-springboot+vue会议管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip
内有各个系统的版本全了
分数阶模型辨识,分数阶模型辨识
大数据基于python的电影天堂数据可视化(源码+配套文档) 系统功能: 登录 、首页 、电影数据管理 、我的信息 关键技术:Python、Django、Mysql、Hadoop、Scrapy、Vue、B/S 技术支持:已测试可正常运行,调试问题可联系客服有偿解决。 更多项目:3000+优质源码,支持【定制】、修改、部署、讲解和文档。
【毕业设计】java-springboot+vue疾病防控综合系统的设计与实现源码(完整前后端+mysql+说明文档+LunW).zip
【毕业设计】java-springboot-vue家具销售电商平台实现源码(完整前后端+mysql+说明文档+LunW).zip
134dfffffffffffffffffffffffffffffff
代码说明: 设置结束时间:通过new Date().getTime()获取当前时间戳,并加上10分钟的毫秒数(10 * 60 * 1000),得到倒计时的结束时间。 更新倒计时:updateCountdown函数计算当前时间与结束时间的差值,并将其转换为分钟和秒数。 显示倒计时:通过console.log输出剩余时间,格式为“剩余时间:X分Y秒”。 停止倒计时:当剩余时间小于或等于0时,清除定时器并输出“时间到!”。 定时器:使用setInterval每秒调用一次updateCountdown函数,实现倒计时的动态更新。 扩展说明: 应用场景:倒计时功能常用于限时抢购、考试计时、活动倒计时等场景。 优化建议:可以将倒计时显示在网页的某个元素中,而不是控制台。例如,使用document.getElementById获取DOM元素并更新其内容。 兼容性:该代码在现代浏览器中均可运行,如果需要兼容旧版浏览器,可以使用var代替const和let。 扩展功能:可以添加声音提示、动画效果等,提升用户体验。
该项目是一个大学生校园兼职平台。该平台使用Java语言开发后台业务逻辑,运用了SpringMVC+Spring+MyBatis框架进行搭建,前台使用jQuery、layUI框架,数据库服务器采用MySQL5.6+对数据进行持久化。其主要功能有:兼职招聘、论坛交流、在线聊天、个人中心、信箱留言、登录注册等功能。
图解AUTOSAR-CP-CommunicationStackTypes逻辑图打包
解释程序的逻辑和变量等等
python学习一些项目和资源