【发布时间】:2016-08-24 13:14:15
【问题描述】:
我想实现一个服务器,它在特定端口上无休止地侦听以接收来自许多客户端的数据(从不并行,只有串行)。我尝试的第一件事是运行服务器,然后串行启动几个客户端(一个接一个)。
这听起来很容易实现,但实际上我遇到了问题,代码只有在服务器代码中至少有一个断点的调试模式下运行时才有效(但与正常运行时相同的错误)断点),对我来说很奇怪。
但是这里是服务器代码:
public class TaskExecutionServer {
public TaskExecutionServer(final int port) {
new Thread() {
@Override
public void run() {
try {
int counter = 0;
ServerSocket serverSocket = new ServerSocket(port);
while(true) {
System.out.println("Waiting for client...");
Socket socket = serverSocket.accept();
System.out.println("Accepted");
InputStream inputStream = socket.getInputStream();
ObjectInputStream objectStream = new ObjectInputStream(inputStream);
while(inputStream.available() > 0 ) {
String to = (String)objectStream.readObject();
System.out.println(to);
System.out.println(++counter);
}
objectStream.close();
inputStream.close();
System.out.println("Closing socket");
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
public static void main(String args[]) {
new TaskExecutionServer(2003);
}
}
这里是客户端代码:
public class TaskSenderClient {
public static void main(String args[]){
try{
Socket s = new Socket("localhost",2003);
OutputStream os = s.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
oos.writeObject("test");
oos.close();
os.close();
s.close();
}catch(Exception e){
System.out.println("Client exception");
e.printStackTrace();
}
}
}
这是在调试模式下运行时的控制台输出,断点位于服务器代码行System.out.println("Accepted");:
Waiting for client...
Accepted
test
1
Closing socket
Waiting for client...
Accepted
test
2
Closing socket
Waiting for client...
Accepted
test
3
Closing socket
Waiting for client...
以及在正常模式下运行/在调试模式下没有断点时的输出:
Waiting for client...
Accepted
test
1
Closing socket
Waiting for client...
Accepted
Closing socket
Waiting for client...
Accepted
Closing socket
Waiting for client...
我没有得到任何例外...有人可以帮忙吗?这是我第一次尝试在 java 中重用套接字连接。
编辑:检查 inputStream.available 会返回不同的值
我刚刚在服务器代码中的while 之前添加了一个System.out.println(inputStream.available());。这打印出来
- 始终
7处于带断点的调试模式 -
7(第一次运行)和0(在所有其他尝试中)之后在非调试模式/没有断点
编辑 2:首先等到 inputStream.available != 0
这个解决方案也适用于我。但是,我在这里删除了这段代码 sn-p,因为检查 available() 似乎不是正确的方法! -> 查看解决方案!
编辑 3:新的服务器代码,它使用 NonEmptyInputStream 检查每个 PushbackInputStream 的非空流:
由于这使用了EOFException,因此对我来说似乎不是最佳解决方案,因此我还删除了此代码 sn-p(而不是参见下面的解决方案)。在下面的 cmets 中讨论了“正确”代码中异常的使用...
【问题讨论】:
-
哦,是的!你完全正确(评论似乎已经被再次删除)......看起来服务器代码“太快”并且过早地检查可用数据!我刚刚在
accept方法之后添加了一个Thread.sleep(100),一切似乎都正常!谢谢,这拯救了我的一天! -
不,不要那样做,这是非常糟糕的做法,而且非常不可靠。只需按照我下面描述的正确方法进行操作
-
一定要使用java.io吗?为什么不使用 java.nio 方法。网上有很多教程。
-
@D.Müller 一个快速的服务器通常是一件好事。正确编码,而不是添加一些任意延迟。
-
你能在问题中检查我的“编辑 2”吗?这对我来说很好,但我不确定这是否正确。