将传入的TCP“命令”转发到函数?

时间:2009-01-26 12:14:24

标签: java sockets

在Java中,您将如何设置一个套接字侦听器,该套接字侦听器侦听一个表示命令和接收的一系列字节的套接字,称为解析传入数据并调用相应命令的方法?

澄清:

我的问题不在于处理命令(也可能是错误代码或对服务器命令的响应),而是创建套接字并监听它。

更多澄清:

我想要做的是模仿以下.Net(C#)代码:

_stream.BeginRead(_data,0, _data.Length, new  
    AsyncCallback(this.StreamEventHandler), _stream);

其中:

  • _stream是从套接字
  • 创建的网络流
  • _data是长度为9的字节数组
  • this.StreamHandler是一个委托(函数指针),在读取数据时执行。

我正在将一个库从C#重写为Java,我正在编写的组件通过TCPIP将命令传递给服务器,但也必须能够将事件/响应冒泡到它上面的层。

在C#中,这似乎是微不足道的,而且在Java中看起来越来越少。

8 个答案:

答案 0 :(得分:1)

有一个小的main方法来设置套接字并侦听传入的连接。将每个连接传递给一个worker对象(可能在它自己的线程中)。

worker对象应该有两个API:服务器和客户端。客户端API获取连接并从中读取数据,服务器API接受连接并将数据写入其中。

我喜欢将这两个保留在一个类中,因为这样可以使两者保持同步变得更加简单。使用辅助类对数据进行编码/解码以进行传输,因此您可以使用单点来决定如何传输整数,命令,选项等。

如果您想更进一步,请定义一个命令类并编写代码以将其序列化为套接字连接并从中读取它。这样,工作对象只需要声明它们处理哪个命令类,服务器/客户端API变得更加简单(以命令类为代价)。

答案 1 :(得分:1)

Starting from my other answer:您要求的具体部分是进入该部分的部分:“魔术就在这里”。它可以用很多方式完成,但其中一个是:

final InputStream in = socket.getInputStream();
// This creates a new thread to service the request.
new Thread(new Runnable(){
  public void run(){
    byte[] retrievedData= new byte[ITEM_LENGTH];
    in.read(retrievedData, 0, ITEM_LENGTH);
    in.close();

    // Here call your delegate or something to process the data
    callSomethingWithTheData(retrievedData);
  }
}).start();

答案 2 :(得分:0)

我会

  1. 将每个命令放入其自己的class中,其中每个类实现特定的interface(例如Command

  2. 创建一个Map<String,Command>,其中包含从每个命令字符串到实现该命令的类的实例的查找表

答案 3 :(得分:0)

TCP连接为您提供了一个InputStream和一个OutputStream。您可以在专用线程上连续轮询InputStream以获取下一个命令(及其输入)。 ByteBuffer.wrap(byte[] array)可能有助于将字节解释为字符,整数,长整数等。您还可以使用serialization传递对象。

答案 4 :(得分:0)

这应该有所帮助。 Lesson 1: Socket Communications

答案 5 :(得分:0)

任何天真的方法很可能无法很好地扩展。

考虑使用REST方法和合适的小型Web服务器。码头通常是一个不错的选择。

答案 6 :(得分:0)

以非常幼稚的方式创建一个套接字:

    mServerSocket = new ServerSocket(port);

    listening = true;

    while (listening) {

      // This call blocks until a connection is made
      Socket socket = serverSocket.accept();

      OutputStream out = socket.getOutputStream();
      InputStream in = socket.getInputStream();

      // Here you do your magic, reading and writing what you need from the streams
      // You would set listening to true if you have some command to close the server
      // remotely

      out.close();
      in.close();
      socket.close();
   }

通常,将输入流的处理委托给其他线程是个好主意,这样您就可以回答下一个请求。否则,您将连续回答所有请求。

您还需要定义某种类型的协议,表明您希望在输入和输出流中使用哪些字节,但是从您的问题来看,它看起来已经有了一个。

答案 7 :(得分:0)

您可以为每个命令创建一个包含一个成员的枚举

interface Comamnd {
    // whatever you expect all command to know to perform their function
    void perform(Context context);
}

enum Commands implements Command{
   ACTIONONE() {
        void perform(Context context) {
             System.out.println("Action One");
        }
   },
   ACTIONTWO() {
        void perform(Context context) {
             System.out.println("Action Two");
        }
   }
}

// initialise
DataInputStream in = new DataInputStream(socket.getInputStream());

// in a loop
byte[] retrievedData= new byte[ITEM_LENGTH];
in.readFully(retrievedData);
String command = new String(retrievedData, 0);
Commands.valueOf(command).perform(context);