客户端与服务端的socket连接后,服务端设置了SetSoTimeout,服务端在readLine阻塞中,过了Timeout时间,服务端的socket抛出异常,并且在抛出异常的catch中设置了服务端对应的socket.close()。这时问题来了。客户端在服务端socket.close()时间后写数据量如DataOutputstream.write(str.getBytes()),DataOutputStream.flush().这两个客户端动作是否会抛出异常??
解决方案 »
- swingImage绘制翻转和旋转的问题
- 请教:Collections.sort()问题
- java简单问题,狂散分了
- UltraEdit如何配置java和javac命令
- 请教问题,win2008服务器,如何才能播放swf文件?
- 开始学习Java了,先给大家送点分,喜欢Eclipse的请进!
- 请各位大侠帮忙了,LDAP的问题
- 关于package包的问题,请高手指教
- 现在深圳有没有招java程序员的公司?
- 启动startWebLogic.cmd后,出现DOS程序执行窗口。提示“Enter password to boot WebLogic server:”,但我却无法输入任何字符。
- java.util.List 求详解
- 请问Class<?>是作什么用的。
我测试好像是没有抛出错误。。奇怪。
DataInputStream is = null;
OutputStream os = null;
try{
socket = new Socket("127.0.0.1",iPort);
socket.setSoTimeout(1000);
is = new DataInputStream(socket.getInputStream());
os = socket.getOutputStream();
Thread.sleep(3000);
os.write("000096789\n".getBytes());
os.flush();
}catch(IOException e){
e.printStackTrace();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
try{
if (is != null) {
is.close();
is = null;
}
if (os != null) {
os.close();
os = null;
}
if (socket != null) {
socket.close();
socket = null;
}
}catch(Exception e){
e.printStackTrace();
}
}
服务端代码片段:
try {
socket.setSoTimeout(1000);
is = new DataInputStream(socket.getInputStream());
os = socket.getOutputStream();
String str = is.readLine();
System.out.println(length);
}catch(Exception e){
e..printStackTrace();
}finally{
try{
if (is != null) {
is.close();
is = null;
}
if (os != null) {
os.close();
os = null;
}
if (socket != null) {
socket.close();
socket = null;
}
}catch(Exception e){
e.printStackTrace();
}
}
查看下有何问题
客户端sleep了3秒。服务端设置timeout为1秒。
socket连接后服务端timeout了。但是客户端的
os.write("000096789\n".getBytes());
os.flush();
都能执行而不报异常。。什么原因呢?
你自己看清楚自己写的代码....
1秒的时候已经抛异常了
os.write("000096789\n".getBytes());
os.flush();
这两句根本就没有执行到...哪里再来的异常那....
Server端的异常并不会影响到这两句吧 ? 我测试了 这两句不会抛出异常。
看下面代码 socket = new Socket("127.0.0.1",8899);
socket.setSoTimeout(1000);
is = new DataInputStream(socket.getInputStream());
os = socket.getOutputStream();
Thread.sleep(10000); socket.setTcpNoDelay(true);
FileOutputStream fo=new FileOutputStream("data.txt");
DataOutputStream dos=new DataOutputStream(fo);
dos.writeUTF(System.currentTimeMillis()+" Client Wakeup time");
os.write("000096789\n".getBytes());
os.flush();
dos.writeUTF(System.currentTimeMillis()+" haha");
while(socket.isClosed()){}
dos.writeUTF(System.currentTimeMillis()+" client close time");
上面是客户端下面是服务器端 if (socket != null) {
FileOutputStream fo=new FileOutputStream("data1.txt");
DataOutputStream dos=new DataOutputStream(fo);
dos.writeUTF(System.currentTimeMillis()+"socket close Time\n");
while(socket.isClosed()==false){}
dos.writeUTF(System.currentTimeMillis()+"socket really close Time\n");
}
这是异常处理的代码 都打印到文件里
理论上我也认为是有异常呀。。但是就是不报异常的所以才求解不知道是不是和TCP协议有关。
客户端调用write 和 flush方法并没有抛出异常。 再执行为这两个操作之后 ,客户端 socket 才关闭。
服务器端 read 方法 由于超时阻塞以后 ,服务器端socket 被关闭, 如果在服务器端再调用 读写方法都会抛出异常 。 但是此时只是服务器端Socket 关闭,并向客户端 提出关闭请求。 客户端Socket 执行Write方法 并顺带确认关闭连接 。在执行完这次 write 后 Socket连接关闭。 如果再在客户端上调用 读写方法,则会抛出异常,你可以试一下。 这是 TCP 关闭时候也需要三次握手决定的。。 具体去看你的计算机网络吧
TCP关闭连接的时候不是一端想关就可以关的,需要三次握手哦 你看一看
我很认同。。但是也是这样想。。再次想问的是,如何在发送write的时候捕捉到socket已经断开了呢?
服务器 端发送 关闭请求 并发送确认关闭祯。 然后自己单方面关闭socket,就是在 服务器端 调用close 方法的是时候 你在服务器端检测此时 socket状态 显示是关闭的,但在客户端却显示未关闭。
当客户端收到服务器端的关闭Socket 请求后, 并不会立即关闭 本端Socket, 会先发送出本端就绪的数据,然后客户端会先把数据发完,然后关闭链接,并 发确认祯关闭链接
它不可以发数据但是还可以接收。TCP的释放是通过两方发送一个FIN 段被确认后那个方向的连接就关闭了,只有两个方向连接都关闭,TCP连接才释放。
所以上面的过程是 ,服务器端申请关闭连接,并发送FIN, 客户端确认,然后服务器端关闭 。 客户端 先把数据发出后,也发FIN申请关闭,此时被 确认后,则SOCket 关闭。JAVA 对底层进行了包装,所以 close 方法的过程具体实现应该是。 一方申请关闭,并不再发送接受数据,
另外一方将剩余数据发出,并关闭连接。
if(socket.isClosed){
}
如果发出后关闭了则说明发出失败。另外就是异步提示,比如 你发了这条后抛出异常 ,那么就提示上一条发送失败。
DataOutputstream.write(str.getBytes()),
DataOutputStream.flush().
这两句不会抛异常的,应为DataOutputstream用的是数据报(UDP协议)发送的,UDP协议的特点:只管发送,不管是否接收到,数据会丢失,发送完后立马关闭流通道,即断开连接,即使服务器端没有超时关闭,当客户端发送数据完了他也会关闭的。说以
如果你用的是TCP协议的话,一定会抛出异常的,TCP特点:建立连接后就会一直开启流通道,不管有无通信,数据安全性高,不会丢失。如果流通道意外中断或是人为中断,建立流的两端都会抛出异常。
为什么说 这句是数据报协议????? 请问 TCP 建立的连接你是怎么用的数据报协议?
DataOutputStream.flush().
你把DataOutputStream 当成DatagramSocket 了???
但是有些环境下,你发这个测试包服务端也认为你发的是正常数据。所以屏蔽这个做法。。有其他大神有解决方案么?
try {
socket.setSoTimeout(1000);
is = new DataInputStream(socket.getInputStream());
os = socket.getOutputStream();
String str = is.readLine();
System.out.println(length);
}catch(Exception e){
e..printStackTrace();
}finally{
try{
if (is != null) {
is.close();
is = null;
}
if (os != null) {
os.close();
os = null;
}
if (socket != null) {
socket.close();
socket = null;
}
}catch(Exception e){
e.printStackTrace();
}
}
把客户端改一下:
socket = new Socket("127.0.0.1", 1209); socket.setSoTimeout(1000);
is = new DataInputStream(socket.getInputStream());
os = socket.getOutputStream();
while (true) {
System.out.println("ok1");
Thread.sleep(3000);
os.write("000096789\n".getBytes());
System.out.println("ok2");
os.flush();
}
你这个改了之后。其实write已经循环了2次了。第二次才报错的。
import java.net.*;public class Server
{
public static void main(String[] args) throws IOException
{
ServerSocket server = new ServerSocket(9999);
Socket socket = server.accept();
socket.close();
}
}
import java.io.*;
import java.net.*;public class Client
{
public static void main(String[] args) throws IOException
{
Socket socket = new Socket("127.0.0.1", 9999);
InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream();
try
{
Thread.sleep(3000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
int t = in.read();
out.write(t);
System.out.println(t);
in.close();
out.close();
socket.close();
}
}
通常 write 的異常是指寫至 buffer 有問題
数据报不是协议,是一种数据流。我想说的是数据报用的是UDP协议来传输的。
if(socket.isClosed){} 只能判断本地socket的。。所以无法实时判断对方是否断开的。。
因为服务器端socket关闭之后会将输入输出流都关闭, 这就意味着客户端soket持有的输入输出流也关闭了,
此时再写数据,肯定会报异常.
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(9999);
Socket socket = server.accept();
//在未有SOCKET client连接上来之前 close方法并未执行。
socket.close();
}
}其实你客户端代码都不需要写,只要在浏览器里面输入:http://localhost:9999/
服务端执行 accept 方法.然后socket就会断开!