为什么我的套接字只能与客户端到服务器而不是服务器到客户端进行通信?

时间:2009-05-15 17:13:32

标签: java networking sockets dispatcher

我编写了一个带有守护程序线程的简单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;
      }
    }
  }
}

2 个答案:

答案 0 :(得分:0)

这是一个非常多的代码。首先,我建议将其删除。

其次,你似乎永远不会打电话给EchoServer.run,但很难看到。

答案 1 :(得分:0)

您还应该设置TCP_NODELAY标志,因为您只发送几个字节。操作系统通常在发送包之前等待更多数据(并且你的flush()对该行为没有影响,因为flush只处理java的缓冲区)。