我编写了一个带有守护程序线程的简单Java调度程序来处理传入的流量,并使用另一个线程发送命令。
问题出现在服务器收到第一条消息,然后客户端/服务器系统卡在服务器尝试向客户端发送响应的位置。两端的套接字只是在服务器发送数据时冻结。
我已将原始问题简化为echo服务器和客户端;我想我必须在代码上犯一个非常愚蠢的错误。我机器上的代码和结果如下。任何人都可以解释出现了什么问题吗?
谢谢!
以下是结果,我们可以看到服务器和客户端在收到第一条消息后卡住了。
Echo Server listening port...
Echo Server: Waiting from client connection.
Connecting to the server.
Connected to the server.
Dispatcher send: 10
Dispatcher send: 11
Dispatcher send: 12
Dispatcher send: 13
Dispatcher read...
Dispatcher read...
Dispatcher readed 10
EchoTest中:
import java.io.*;
import java.net.*;
public class EchoTest {
public static void main(String[] args) {
EchoServer.listen();
EchoClient client = new EchoClient();
EchoServer server = EchoServer.accept();
}
}
客户端和服务器:
class EchoClient implements Runnable {
private static final int PORT = 13244;
Socket socket;
Disp disp;
Thread client;
public EchoClient() {
client = new Thread(this);
client.start();
}
public void run() {
try {
System.out.println("Connecting to the server.");
Socket socket = new Socket("localhost", PORT);
System.out.println("Connected to the server.");
disp = new Disp(socket);
disp.send(10);
disp.send(11);
disp.send(12);
disp.send(13);
} catch(IOException e) {
System.out.println("Would not connect to local host: " + PORT);
System.exit(-1);
}
}
public void send(int m) {
disp.send(m);
System.out.println("Sent message " + m);
int echo = disp.getMsg();
if(m == echo) {
System.out.println("Message " + m + "sent and received.");
} else {
System.out.println("Message " + m + "cannot be echoed correctly.");
}
}
}
class EchoServer implements Runnable{
private static final int PORT = 13244;
private static ServerSocket serverSocket;
Disp disp;
public EchoServer(Socket s) {
disp = new Disp(s);
}
public static void listen() {
System.out.println("Echo Server listening port...");
try {
serverSocket = new ServerSocket(PORT);
} catch (IOException e) {
System.out.println("Could not listen on port: " + PORT);
System.exit(-1);
}
}
public static EchoServer accept(){
try {
System.out.println("Echo Server: Waiting from client connection.");
return new EchoServer(serverSocket.accept());
} catch(IOException e) {
System.out.println("Couldn't accept connection from client.");
System.exit(-1);
}
return null;
}
public void run() {
while(true) {
int m = disp.getMsg();
disp.send(m);
}
}
}
DISP:
class Disp implements Runnable{
int msg = -1;
Socket socket;
BufferedInputStream input;
DataInputStream dis;
BufferedOutputStream output;
DataOutputStream dos;
Thread daemon;
public Disp(Socket s) {
this.socket = s;
try{
input = new BufferedInputStream(socket.getInputStream());
dis = new DataInputStream(input);
output = new BufferedOutputStream(socket.getOutputStream());
dos = new DataOutputStream(output);
}catch(IOException e) {
}
daemon = new Thread(this);
daemon.start();
}
public void run() {
while(true) {
int m = get();
setMsg(m);
}
}
public void send(int m) {
synchronized(dos) {
try{
System.out.println("Dispatcher send: " + m);
dos.writeInt(m);
dos.flush();
} catch(IOException e) {
}
}
}
public int get() {
System.out.println("Dispatcher read...");
synchronized(dis) {
try{
int m = dis.readInt();
System.out.println("Dispatcher readed " + m);
return m;
} catch(IOException e) {
}
}
return -1;
}
synchronized public void setMsg(int m) {
while(true) {
if(msg == -1) {
try {
wait();
} catch(InterruptedException e) {
}
} else {
msg = m;
notifyAll();
}
}
}
synchronized public int getMsg() {
while(true) {
if(msg != -1) {
try {
wait();
} catch(InterruptedException e) {
}
} else {
notifyAll();
return msg;
}
}
}
}
答案 0 :(得分:0)
这是一个非常多的代码。首先,我建议将其删除。
其次,你似乎永远不会打电话给EchoServer.run
,但很难看到。
答案 1 :(得分:0)
您还应该设置TCP_NODELAY标志,因为您只发送几个字节。操作系统通常在发送包之前等待更多数据(并且你的flush()对该行为没有影响,因为flush只处理java的缓冲区)。