- 浏览: 141355 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
H4X0R:
else if(head[0]==-17 && ...
java读取txt文件乱码解决方案 -
浮生若梦dc:
ps -ef | grep java 查出所有java进程;p ...
Linux下查看指定端口占用进程号 -
浮生若梦dc:
...
jvisualvm下使用JMX方式远程监控tomcat7 -
lfl2011:
dove19900520 写道没看到你的code值是在哪用的啊 ...
java读取txt文件乱码解决方案 -
dove19900520:
没看到你的code值是在哪用的啊?
java读取txt文件乱码解决方案
ServerSocket类有以下三个选项:
1. SO_TIMEOUT: 设置accept方法的超时时间。
2. SO_REUSEADDR:设置服务端同一个端口是否可以多次绑定。
3. SO_RECBUF:设置接收缓冲区的大小。
一、SO_TIMEOUT选项
可以通过SeverSocket类的两个方法(setSoTimeout和getSoTimeout)来设置和获得SO_TIMEOUT选项的值,这两个方法的定义如下:
public synchronized void setSoTimeout(int timeout) throws SocketException
public synchronized int getSoTimeout() throws IOException
public synchronized int getSoTimeout() throws IOException
setSoTimeout方法的timeout参数表示accept方法的超时时间,单位是毫秒。在通常情况下,ServerSocket类的accept方法在等待客户端请求时处于无限等待状态。如HTTP服务器在没有用户访问网页时会一直等待用户的请求。一般不需要对服务端设置等待客户端请求超时,但在某些特殊情况下,服务端规定客户端必须在一定时间内向服务端发出请求,这时就要设置等待客户端请求超时,也就是accept方法的超时时间。当设置客户端请求超时后,accept方法在等待超时时间后抛出一个SocketTimeoutException异常。下面的代码演示了如何设置和获得SO_TIMEOUT选项的值,超时时间通过命令行参数方式传入AcceptTimeout。
package server;
import java.net.*;
public class AcceptTimeout
{
public static void main(String[] args) throws Exception
{
if (args.length == 0)
return;
ServerSocket serverSocket = new ServerSocket(1234);
int timeout = Integer.parseInt(args[0]);
serverSocket.setSoTimeout(Integer.parseInt(args[0]));
System.out.println((timeout > 0) ? "accept方法将在"
+ serverSocket.getSoTimeout() + "毫秒后抛出异常!" : "accept方法永远阻塞!");;
serverSocket.accept();
}
}
import java.net.*;
public class AcceptTimeout
{
public static void main(String[] args) throws Exception
{
if (args.length == 0)
return;
ServerSocket serverSocket = new ServerSocket(1234);
int timeout = Integer.parseInt(args[0]);
serverSocket.setSoTimeout(Integer.parseInt(args[0]));
System.out.println((timeout > 0) ? "accept方法将在"
+ serverSocket.getSoTimeout() + "毫秒后抛出异常!" : "accept方法永远阻塞!");;
serverSocket.accept();
}
}
执行下面的命令:
java server.AcceptTimeout 3000
运行结果:
accept方法将在3000毫秒后抛出异常!
Exception in thread "main" java.net.SocketTimeoutException: Accept timed out
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
at java.net.ServerSocket.implAccept(ServerSocket.java:450)
at java.net.ServerSocket.accept(ServerSocket.java:421)
at chapter5.AcceptTimeout.main(AcceptTimeout.java:16)
Exception in thread "main" java.net.SocketTimeoutException: Accept timed out
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
at java.net.ServerSocket.implAccept(ServerSocket.java:450)
at java.net.ServerSocket.accept(ServerSocket.java:421)
at chapter5.AcceptTimeout.main(AcceptTimeout.java:16)
setSoTimeout方法可以在ServerSocket对象绑定端口之前调用,也以在绑定端口之后调用。如下面的代码也是正确的:
ServerSocket serverSocket = new ServerSocket();
serverSocket.setSoTimeout(3000);
serverSocket.bind(new InetSocketAddress(1234));
serverSocket.setSoTimeout(3000);
serverSocket.bind(new InetSocketAddress(1234));
st1":*{behavior:url(#ieooui) }
二、SO_REUSEADDR选项
SO_REUSEADDR选项决定了一个端口是否可以被绑定多次。可以通过SeverSocket类的两个方法(setReuseAddres和getReuseAddress)来设置和获得SO_TIMEOUT选项的值,这两个方法的定义如下:
public void setReuseAddress(boolean on) throws SocketException
public boolean getReuseAddress() throws SocketException
public boolean getReuseAddress() throws SocketException
在大多数操作系统中都不允许一个端口被多次绑定。如果一个ServerSocket对象绑定了已经被占用的端口,那么ServerSocket的构造方法或bind方法就会抛出一个BindException异常。
Java提供这个选项的主要目的是为了防止由于频繁绑定释放一个固定端口而使系统无法正常工作。当ServerSocket对象关闭后,如果ServerSocket对象中仍然有未处理的数据,那么它所绑定的端口可能在一段时间内不会被释放。这就会造成其他的ServerSocket对象无法绑定这个端口。在设置这个选项时,如果某个端口是第一次被绑定,无需调用setReuseAddress方法,而再次绑定这个端口时,必须使用setReuseAddress方法将这个选项设为true。而且这个方法必须在调用bind方法之前调用。下面的代码演示了如何设置和获得这个选项的值:
package server;
import java.net.*;
public class TestReuseAddr1
{
public static void main(String[] args) throws Exception
{
ServerSocket serverSocket1 = new ServerSocket(1234);
System.out.println(serverSocket1.getReuseAddress());
ServerSocket serverSocket2 = new ServerSocket();
serverSocket2.setReuseAddress(true);
serverSocket2.bind(new InetSocketAddress(1234));
ServerSocket serverSocket3 = new ServerSocket();
serverSocket3.setReuseAddress(true);
serverSocket3.bind(new InetSocketAddress(1234));
}
}
import java.net.*;
public class TestReuseAddr1
{
public static void main(String[] args) throws Exception
{
ServerSocket serverSocket1 = new ServerSocket(1234);
System.out.println(serverSocket1.getReuseAddress());
ServerSocket serverSocket2 = new ServerSocket();
serverSocket2.setReuseAddress(true);
serverSocket2.bind(new InetSocketAddress(1234));
ServerSocket serverSocket3 = new ServerSocket();
serverSocket3.setReuseAddress(true);
serverSocket3.bind(new InetSocketAddress(1234));
}
}
运行结果:false
在上面代码中第一次绑定端口1234,因此,serverSocket1对象无需设置SO_REUSEADDR选项(这个选项在大多数操作系统上的默认值是false)。而serverSocket2和serverSocket3并不是第一次绑定端口1234,因此,必须设置这两个对象的SO_REUSEADDR值为true。在设置SO_REUSEADDR选项时要注意,必须在ServerSocket对象绑定端口之前设置这个选项。
也许有的读者可能有这样的疑问。如果多个ServerSocket对象同时绑定到一个端口上,那么当客户端向这个端口发出请求时,该由哪个ServerSocket对象来接收客户端请求呢?在给出答案之前,让我们先看看下面的代码的输出结果是什么。
package server;
import java.net.*;
public class TestReuseAddr2 extends Thread
{
String s;
public void run()
{
try
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(1234));
Socket socket = serverSocket.accept();
System.out.println(s + ":" + socket);
socket.close();
serverSocket.close();
}
catch (Exception e)
{
}
}
public TestReuseAddr2(String s)
{
this.s = s;
}
public static void main(String[] args)
{
for (int i = 1; i <= 5; i++)
new TestReuseAddr2("ServerSocket" + i).start();
}
}
import java.net.*;
public class TestReuseAddr2 extends Thread
{
String s;
public void run()
{
try
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.setReuseAddress(true);
serverSocket.bind(new InetSocketAddress(1234));
Socket socket = serverSocket.accept();
System.out.println(s + ":" + socket);
socket.close();
serverSocket.close();
}
catch (Exception e)
{
}
}
public TestReuseAddr2(String s)
{
this.s = s;
}
public static void main(String[] args)
{
for (int i = 1; i <= 5; i++)
new TestReuseAddr2("ServerSocket" + i).start();
}
}
执行下面的命令:
java server.TestReuseAddr2
连续执行5次下面的命令:
telnet localhost 1234
执行结果:
ServerSocket1:Socket[addr=/127.0.0.1,port=11724,localport=1234]
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]
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对象将永远无法接收客户端请求。读者可以将serverSocket.close()去掉,再执行上面操作步骤,看看会有什么结果。
st1":*{behavior:url(#ieooui) } 三、SO_RCVBUF选项
st1":*{behavior:url(#ieooui) } 三、SO_RCVBUF选项
可以通过SeverSocket类的两个方法(setReceiveBufferSize和getReceiveBufferSize)来设置和获得SO_RCVBUF选项的值,这两个方法的定义如下:
public synchronized void setReceiveBufferSize (int size) throws SocketException
public synchronized int getReceiveBufferSize() throws SocketException
public synchronized int getReceiveBufferSize() throws SocketException
其中size参数表示接收缓冲区的大小,单位是字节。设置了ServerSocket类的SO_RCVBUF选项,就相当于设置了Socket对象的接收缓冲区大小。这个Socket对象是由accept返回的。下面积代码演示了如何使用这两个方法来设置和获得接收缓冲区的大小:
package server;
import java.net.*;
public class TestReceiveBufferSize
{
public static void main(String[] args) throws Exception
{
ServerSocket serverSocket = new ServerSocket(1234);
serverSocket.setReceiveBufferSize(2048); // 将接收缓冲区设为2K
while (true)
{
Socket socket = 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();
}
}
}
import java.net.*;
public class TestReceiveBufferSize
{
public static void main(String[] args) throws Exception
{
ServerSocket serverSocket = new ServerSocket(1234);
serverSocket.setReceiveBufferSize(2048); // 将接收缓冲区设为2K
while (true)
{
Socket socket = 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();
}
}
}
执行如下命令:
java server.TestReceiveBufferSize
执行如下三个命令 (192.168.18.100为本机IP地址):
telnet 192.168.18.100 1234
telnet localhost 1234
telnet 192.168.18.100 1234
telnet localhost 1234
telnet 192.168.18.100 1234
运行结果:
serverSocket:2048
socket:2048
serverSocket:2048
socket:1024
serverSocket:2048
socket:2048
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 serverSocket = new ServereSocket();
serverSocket. setReceiveBufferSize(100 * 1024); // 将接收缓冲区的大小设为100K。
serverSocket.bind(new InetSocketAddress(1234));
serverSocket. setReceiveBufferSize(100 * 1024); // 将接收缓冲区的大小设为100K。
serverSocket.bind(new InetSocketAddress(1234));
st1":*{behavior:url(#ieooui) }
一般情况下,并不需要设置这个选项,它的默认值(一般为8K)足可以满足大多数情况。但有时为了适应特殊的需要,必须更改接收缓冲区的值。如在一些网络游戏中,需要实时地向服务器传送各种动作、指令信息。这就需要将接收缓冲区设小一点。这样可以在一定程度上增加游戏客户端的灵敏度。如果需要传送大量的数据,如HTTP、FTP等协议。这就需要较大的接收缓冲区。
四、设置ServerSocket的性能偏好
四、设置ServerSocket的性能偏好
在Java SE5.0及以上版本中为ServerSocket类增加了一个setPerformancePreferences方法。这个和方法和Socket类中的setPerformancePreferences的作用一样,用来设置连接时间、延迟和带宽的相对重要性。setPerformancePerferences方法的定义如下:
public void setPerformancePreferences(int connectionTime, int latency, int bandwidth)
发表评论
-
Tomcat项目生成文件出现文件名乱码问题
2019-09-03 17:57 7821. 本人在linux服务器的tomcat下部署一个war ... -
Java环境中编码处理
2016-11-03 11:29 0https://confluence.atlassian.co ... -
Java生成验证码
2016-05-03 13:54 0为了防止用户恶意,或者使用软件外挂提交一些内容,就得用验证码 ... -
Java生成二维码
2016-05-03 11:48 0项目中用到了二维码扫描的技术,用的是Google提供的ZXi ... -
Java DelayQueue使用实例
2016-02-18 23:43 1354DelayQueue是一个支持延时获取元素的无界阻塞队列。 ... -
Java Base64 加密解密
2016-02-18 23:09 1011使用JDK的类 BASE64Decoder BASE64E ... -
类似于地区树形结构的构造
2016-01-23 20:59 874在做项目中经常会用到地区的树形结构,而在数据库中我们一般存储 ... -
VTD-XML技术解析XML实例
2015-03-27 12:01 1801VTD-XML是一种无提取的XML解析方法,它较好的解决了 ... -
Java生成短链
2015-03-04 10:50 2182生成思路: 1.将"原始链接(长链接)+ ... -
Java中字符串的应用
2014-12-12 20:54 598intern 方法 返回从字符串常量池中唯一的字 ... -
并发集合ConcurrentSkipListMap的性能测试
2014-12-10 17:47 1516ConcurrentSkipListMap是Doug ... -
AtomicInteger在多线程下的原子性测试
2014-12-10 16:18 1199使用AtomicInteger做计数器的一个例子: ... -
Java中实例方法和静态方法在多线程下加锁和不加锁的访问情况
2014-12-08 18:17 799第一个例子是同一实例方法加锁和不加锁在多线程情况下的 ... -
Java应用架构常用的框架,侧重MVC和restful应用
2014-10-21 17:24 1704Struts是采用Java Servlet/JavaSer ... -
Protocol Buffers 入门应用
2014-10-13 20:43 1548Protocol Buffers是Google开源 ... -
Eclipse反编译工具Jad.exe及插件JadClipse配置
2014-07-06 15:14 11241、下载所需文件 JadClipse,http://ja ... -
Java远程调试
2014-04-24 18:20 986客户端Eclipse配置 服务端启动脚本 ... -
解决List的ConcurrentModificationException的几种方法
2014-04-03 19:15 1298import java.util.regex. ... -
使用Java正则表达式分析处理日志
2014-03-14 11:29 0一般的日志输出的信息有日期时间,哪个线程,执行某个任务花 ... -
Java 完美判断中文字符
2013-09-06 11:14 1415Java判断一个字符串是否有中文一般情况是利用Unicod ...
相关推荐
java网络编程:控制台输入,服务端代码!
https://blog.csdn.net/qq_29542611/article/details/86371353 MFC:Socket编程—TCP服务端和多个客户端通信 示例代码
本代码为java socket网络编程实例代码,包括客户端和服务端,实现客户端发送消息,服务端接收并反馈消息。 server.java为服务端代码。 client.java为客户端代码。
socket网络编程实例代码分为服务端和客户端,client是客户端的文件。server是服务端的文件。可以作为参考
此代码通过Java编程实现了基于Socket的网络通信,通信时有两个界面,分别是服务端、客户端,可发消息,界面上有显示,默认是本机的IP地址,代码可用JCreator直接打开,文件是.java形式。
JAVA 网络编程服务器端例程,一个测试socket通信的比较好的例程
java源码:服务端JavaScript框架 RingoJS.rar
适合java初学者,可以帮助你们了解简单的图形化界面,和网络编程
使用java开发,swing界面,TCP客户端和服务端简单通信实验
主要介绍了Java基于socket实现的客户端和服务端通信功能,结合完整实例形式分析了Java使用socket建立客户端与服务器端连接与通信功能,需要的朋友可以参考下
Java网络编程_实现客户端与服务端的交互,描绘的很详细,很适合新手阅读
自己写的Java多线程Socket服务端,可以接收网络调试助手或者其它客户端发来的数据
在Qt的服务端上,不单单会用到服务端本身的API,对连接上来的客户端,也需要进行数据交互,也要用到一些收发包相关的API操作; 1、相关的库和类 Qt下使用tcp协议,需要在工程的pro文件中添加: QT += network ...
Java网络编程-Socket-文件传输小案例学习资料分享c
1.采用重叠I/O方式实现的socket网络编程,异步非阻塞方式,代码效率比阻塞式的socket编程方式高。2.实现了TCP server方式,只用于服务端,可以支持多客户端。3.可以使用在各种场合用于监控网络数据。4.代码封装成库...
用户登录注册功能,有客户端与服务器,代码有备注,功能完善,可以判断登录信息是否重复等,密码信息在本地文档。
java写的异步socket服务端源代码,包括一些指令操作! 开发异步服务端的时候可以借鉴一下。 只有一个java文件,就完成异步服务端的功能。 不要错过哦,10分的资源分贵是贵点,但是真的值。
基于SOCKET编程,采用TCP连接方法编写的服务端,可以连接指定连接个数,监听客户端,然后接受客户端发送过来的内容,也可以发送数据到客户端。
基于C#网络通信编程,SOCKET客户端与服务端通信协议的程序连
《Linux多线程服务端编程:使用muduo C++网络库》.(陈硕) 完整版并且带书签,对于网络编程有很好的参考价值。