ServerSocket超时问题

J2EE 码拜 10年前 (2015-05-11) 1616次浏览 0个评论

我新建一个ServerSocket,代码如下:
ServerSocket serviceSocket = new ServerSocket(3434);
while (true) {
Socket socket = null;
// 接收客户连接,只要客户进行了连接,就会触发accept();从而建立连接
Socket socket = serviceSocket.accept();
//设置无通讯超时时间,tcp链接超过空闲时间就会抛出异常然后关闭连接
socket.setSoTimeout(60000);
service.execute(new SocketHandler(socket));
}

SocketHandler的代码如下:
 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
logger.info(“reader流已经建立。。。。”);
StringBuffer socketMsg = new StringBuffer();
String msg = null;
while ((msg = br.readLine()) != null) {
       socketMsg.append(msg); 
logger.info(“服务器端接受信息:” + msg);
if (msg.endsWith(“#”)) {//遇到#时就结束接收  
          break;  
 }  
}
logger.info(“服务器端接受信息:” + socketMsg.toString());
现在出现一个问题,客户端socket已经连接成功,BufferedReader流也已经新建成功了,但是在br.readLine()的时候抛出一个异常:
java.net.SocketTimeoutException: Read timed out
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
请高手指教,谢谢

客户端有没有对输出流进行flush
额,不知道你客户端的代码, 超时是不是手工输入太慢了,
超时还可能是另一个原因,就是接收的”#”带有回车/换行,所以该退出时却没有退出,还在接收,然后就超时了, lz可以试试把判断条件改为

if (msg.trim().endsWith("#")) {//遇到#时就结束接收  
          break;  
 } 
引用 2 楼 u011004037 的回复:

额,不知道你客户端的代码, 超时是不是手工输入太慢了,
超时还可能是另一个原因,就是接收的”#”带有回车/换行,所以该退出时却没有退出,还在接收,然后就超时了, lz可以试试把判断条件改为

if (msg.trim().endsWith("#")) {//遇到#时就结束接收  
          break;  
 } 

客户端是一个车载系统,根据他们说,他们是发送到附近的基站,然后通过基站发送数据的,应该和输入快慢没什么关系,还有我自己写了socket测试,因为有(msg = br.readLine()) != null 这个判断条件为前提,所以endsWith(“#”)这个应该没关系的

@wangxf_8341 :客户端有没有对输出流进行flush   这个应该是有道理的,我问下
引用 1 楼 wangxf_8341 的回复:

客户端有没有对输出流进行flush

我问了下,他们是有flush的,而且我们这个抓了下包,发现是可以收到他们发送的消息的,这是为什么那

引用 5 楼 guoqiang139555 的回复:
Quote: 引用 1 楼 wangxf_8341 的回复:

客户端有没有对输出流进行flush

我问了下,他们是有flush的,而且我们这个抓了下包,发现是可以收到他们发送的消息的,这是为什么那

lz可以打印一下啊, 试试这个代码, 然后把日志发出来呗

while ((msg = br.readLine()) != null) {
	socketMsg.append(msg); 
	logger.info("服务器端接受信息: [" + msg + "]");
	if (msg.endsWith("#")) {//遇到#时就结束接收  
		logger.info( "退出" );
		break;
	}
}
引用 6 楼 u011004037 的回复:
Quote: 引用 5 楼 guoqiang139555 的回复:
Quote: 引用 1 楼 wangxf_8341 的回复:

客户端有没有对输出流进行flush

我问了下,他们是有flush的,而且我们这个抓了下包,发现是可以收到他们发送的消息的,这是为什么那

lz可以打印一下啊, 试试这个代码, 然后把日志发出来呗

while ((msg = br.readLine()) != null) {
	socketMsg.append(msg); 
	logger.info("服务器端接受信息: [" + msg + "]");
	if (msg.endsWith("#")) {//遇到#时就结束接收  
		logger.info( "退出" );
		break;
	}
}

没用的,在执行while ((msg = br.readLine()) != null) { 这句话的时候报的错,所以你们的日志不会打印出来的

引用 6 楼 u011004037 的回复:
Quote: 引用 5 楼 guoqiang139555 的回复:
Quote: 引用 1 楼 wangxf_8341 的回复:

客户端有没有对输出流进行flush

我问了下,他们是有flush的,而且我们这个抓了下包,发现是可以收到他们发送的消息的,这是为什么那

lz可以打印一下啊, 试试这个代码, 然后把日志发出来呗

while ((msg = br.readLine()) != null) {
	socketMsg.append(msg); 
	logger.info("服务器端接受信息: [" + msg + "]");
	if (msg.endsWith("#")) {//遇到#时就结束接收  
		logger.info( "退出" );
		break;
	}
}

没用的,在执行while ((msg = br.readLine()) != null) { 这句话的时候报的错,所以里面的日志不会打印出来的 

也就是说,一次都没有读进来?
那要不试试用BufferedReader的这个方法读, 一次10个字符, 
public int read(char[] cbuf, int off,  int len)
另外, lz不是抓包了吗? 看看他们连接的时间, 还有他们发送一个回车符或者结束连接的时间, 之间的差值是不是大于1分钟
引用 9 楼 u011004037 的回复:

也就是说,一次都没有读进来?
那要不试试用BufferedReader的这个方法读, 一次10个字符, 
public int read(char[] cbuf, int off,  int len)
另外, lz不是抓包了吗? 看看他们连接的时间, 还有他们发送一个回车符或者结束连接的时间, 之间的差值是不是大于1分钟

我用InputStreamReader这个试过,看了下发送时间,是指一分钟以内发过来的

楼主  你确定你接收到数据了   不是连接就行了  你看是否接收到数据

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

引用

public String readLine()    throws IOException
读取一个文本行。通过下列字符之一即可认为某行已终止:换行 (“”\n””)、回车 (“”\r””) 或回车后直接跟着换行。
返回:
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
抛出:
IOException – 如果发生 I/O 错误

这是readLine的文档, 也就是说没有换行之类的字符或者到达末尾, 是不会返回的, 
额, 我们需要关注的是换行符什么时候到达, 而不是数据什么时候到达, 
lz可以看看这个Server/Client通信的典型例子的修改版

import java.net.*;
import java.io.*;

public class SocketClient{
	public static void main( String[] args ) throws Exception{
		Socket client = new Socket( "127.0.0.1", 40000 );
		BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
		PrintStream out = new PrintStream(client.getOutputStream());
		BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));

		while(true){
			System.out.println("输入信息>");
			String str = input.readLine();
			out.print(str);
			//System.out.println(buf.readLine());
			if( "exit".equalsIgnoreCase(str) ){
				break;
			}
		}
	}
}
import java.io.*;
import java.net.*;

public class SocketServer{
	public static void main(String[] args) throws Exception{
		ServerSocket server = new ServerSocket(40000);
		Socket client = server.accept();
		PrintStream out = new PrintStream(client.getOutputStream());
		BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
		client.setSoTimeout(60000);

		while(true){
			System.out.println( buf.read() );   // 当用这个读的时候, 没有一点问题, 只不过读到的是ASCII码
			System.out.println( buf.readLine() );  // 用这个读的时候有两种可能, 超时 或者 客户端关闭连接, 抛出异常....
		}
	}
}
引用 12 楼 u011004037 的回复:
引用

public String readLine()    throws IOException
读取一个文本行。通过下列字符之一即可认为某行已终止:换行 (“”\n””)、回车 (“”\r””) 或回车后直接跟着换行。
返回:
包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null
抛出:
IOException – 如果发生 I/O 错误

这是readLine的文档, 也就是说没有换行之类的字符或者到达末尾, 是不会返回的, 
额, 我们需要关注的是换行符什么时候到达, 而不是数据什么时候到达, 
lz可以看看这个Server/Client通信的典型例子的修改版

import java.net.*;
import java.io.*;

public class SocketClient{
	public static void main( String[] args ) throws Exception{
		Socket client = new Socket( "127.0.0.1", 40000 );
		BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
		PrintStream out = new PrintStream(client.getOutputStream());
		BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));

		while(true){
			System.out.println("输入信息>");
			String str = input.readLine();
			out.print(str);
			//System.out.println(buf.readLine());
			if( "exit".equalsIgnoreCase(str) ){
				break;
			}
		}
	}
}
import java.io.*;
import java.net.*;

public class SocketServer{
	public static void main(String[] args) throws Exception{
		ServerSocket server = new ServerSocket(40000);
		Socket client = server.accept();
		PrintStream out = new PrintStream(client.getOutputStream());
		BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
		client.setSoTimeout(60000);

		while(true){
			System.out.println( buf.read() );   // 当用这个读的时候, 没有一点问题, 只不过读到的是ASCII码
			System.out.println( buf.readLine() );  // 用这个读的时候有两种可能, 超时 或者 客户端关闭连接, 抛出异常....
		}
	}
}

郁闷还是不行,我同时用bur.read(),bur.readLine()都试过了,我自己测试的时候怎么都行,但是用他们那个GPS设备发的时候就是只能收到流,流里面是有数据的,但是就是取不到数据,

额 lz确定他们正确的发送数据了? 如果方便, 可否提供一下抓的包,还有lz现在的程序版本中的接受数据部分.
引用 14 楼 u011004037 的回复:

额 lz确定他们正确的发送数据了? 如果方便, 可否提供一下抓的包,还有lz现在的程序版本中的接受数据部分.

ServerSocket超时问题ServerSocket超时问题ServerSocket超时问题

代码就是
public class SocketServer{
    public static void main(String[] args) throws Exception{
        ServerSocket server = new ServerSocket(40000);
        Socket client = server.accept();
        PrintStream out = new PrintStream(client.getOutputStream());
        BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
        client.setSoTimeout(60000);
 
        while(true){
            System.out.println( buf.read() );   // 当用这个读的时候, 没有一点问题, 只不过读到的是ASCII码
            System.out.println( buf.readLine() );  // 用这个读的时候有两种可能, 超时 或者 客户端关闭连接, 抛出异常….
        }
    }
}
这样的,这两种方式我都试过了

我截图里是三次握手时间和第三张图是流里面发送的内容
弱弱的问下,刚才我问了下他们说客户端是用.net写的,这个有影响吗
引用 17 楼 guoqiang139555 的回复:

弱弱的问下,刚才我问了下他们说客户端是用.net写的,这个有影响吗

额, 这个应该没有影响啊, 网络和使用什么语言又没有关系, 看着发过来的信息没有换行符和回车符(0a/0d),readline收不到还可以理解,  但是read应该能收到啊, 为啥收不到勒?

引用 10 楼 guoqiang139555 的回复:

我用InputStreamReader这个试过,看了下发送时间,是指一分钟以内发过来的

引用 13 楼 guoqiang139555 的回复:

郁闷还是不行,我同时用bur.read(),bur.readLine()都试过了,我自己测试的时候怎么都行,但是用他们那个GPS设备发的时候就是只能收到流,流里面是有数据的,但是就是取不到数据,

难道用InputStreamReader可以收到吗?lz的意思是不是, java程序能收到数据,比如使用InputStreamReader就可以? 只是无法取出?

引用 18 楼 u011004037 的回复:
Quote: 引用 17 楼 guoqiang139555 的回复:

弱弱的问下,刚才我问了下他们说客户端是用.net写的,这个有影响吗

额, 这个应该没有影响啊, 网络和使用什么语言又没有关系, 看着发过来的信息没有换行符和回车符(0a/0d),readline收不到还可以理解,  但是read应该能收到啊, 为啥收不到勒?

引用 10 楼 guoqiang139555 的回复:

我用InputStreamReader这个试过,看了下发送时间,是指一分钟以内发过来的

引用 13 楼 guoqiang139555 的回复:

郁闷还是不行,我同时用bur.read(),bur.readLine()都试过了,我自己测试的时候怎么都行,但是用他们那个GPS设备发的时候就是只能收到流,流里面是有数据的,但是就是取不到数据,

难道用InputStreamReader可以收到吗?lz的意思是不是, java程序能收到数据,比如使用InputStreamReader就可以? 只是无法取出?

流里面是有数据的,用InputStreamReader和BufferedReader 都取不到数据,然后客户端是用.net写的,这个有影响没

额, lz想想, 多少网站使用的.net, php, jsp, 客户端呢? pc上应该是C, 不照样通信了,  其实网络本来就适应不同架构不同系统之间的互联, 怎么会和语言有关系呢?
不过可能会在一些细节上不一样, 导致不好对接吧,  比如 这个会自动刷新, 那个会积累到一定程度再发,我也不知道, 没学过.net
lz最好在过一遍自己的代码, 看看有没有什么细节上有错误,
引用 20 楼 u011004037 的回复:

额, lz想想, 多少网站使用的.net, php, jsp, 客户端呢? pc上应该是C, 不照样通信了,  其实网络本来就适应不同架构不同系统之间的互联, 怎么会和语言有关系呢?
不过可能会在一些细节上不一样, 导致不好对接吧,  比如 这个会自动刷新, 那个会积累到一定程度再发,我也不知道, 没学过.net
lz最好在过一遍自己的代码, 看看有没有什么细节上有错误,

是的呀,说到底都是底层的网络连接,而且输入流里面已经有数据了,说明他们已经发过来了,但是我就是取不出来。。。

引用 21 楼 guoqiang139555 的回复:
Quote: 引用 20 楼 u011004037 的回复:

额, lz想想, 多少网站使用的.net, php, jsp, 客户端呢? pc上应该是C, 不照样通信了,  其实网络本来就适应不同架构不同系统之间的互联, 怎么会和语言有关系呢?
不过可能会在一些细节上不一样, 导致不好对接吧,  比如 这个会自动刷新, 那个会积累到一定程度再发,我也不知道, 没学过.net
lz最好在过一遍自己的代码, 看看有没有什么细节上有错误,

是的呀,说到底都是底层的网络连接,而且输入流里面已经有数据了,说明他们已经发过来了,但是我就是取不出来。。。

刚刚我试了一下, 在linux下, C语言写的客户端和Java写的服务端可以互相通信, 没有一点问题…

还是建议lz看看自己的代码, 好多看似不应该的错误都是非常非常非常细小的失误导致的, 而且极难发现, 耐心看看, 调试一下试试吧…
额, 我突然想起来, lz的程序应该还没有正式运行吧, 那客户端怎么知道lz的服务器端启动了, 然后主动连接lz的程序呢?
引用 24 楼 u011004037 的回复:

额, 我突然想起来, lz的程序应该还没有正式运行吧, 那客户端怎么知道lz的服务器端启动了, 然后主动连接lz的程序呢?

额。。。。就是在现网运行的时候发现这个错误的

40分
根据你们的响应报文可以看出来是以”#”作为结束符的,而readLine方法需要”\n”作为结束符,所以readLine会一直等待,直到socket连接超时。因此,你们可以尝试通过逐个字符进行读取,如下:

BufferedReader in = new BufferedReader(new InputStreamReader(
						socket.getInputStream()));
				StringBuffer sb = new StringBuffer();

				int b ;
				// ASCII中的#为35
				while ((b = in.read()) != 35) {
					sb.append((char)b);
				}
				System.out.println("Server:"+sb.toString());

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明ServerSocket超时问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!