Java客户端/服务器应用程序与套接字?

21

我正在编写一个Java包,将被另一种语言(matlab)调用。如果我的matlab进程结束,我希望Java进程继续运行。每当matlab重新启动时,它应该能够与现有的正在运行的进程通信。因此,我认为需要使用客户端/服务器模型通过套接字让Java应用程序进行通信。我设想有一组简单的函数:

  • startServer(host, port)
  • runCommand(server, command...)
  • stopServer(host, port)

我以前从未做过类似的事情。我是否正确地考虑了这个问题,或者有没有更容易构建独立于其父进程的应用程序的方法?最佳的现代化方式是什么(例如,是否有任何好的Apache包)?是否可以提供一个简单的演示或将我指向通过套接字与进程通信的教程?

[编辑] 为了澄清,matlab能够实例化一个Java对象并在其中运行Java代码。因此,在matlab中,startServer()函数将运行Java代码,检查该端口上是否已经有Java进程正在运行,如果没有,则启动服务器进程。

我并不一定要使用套接字(如果不明显的话,我主要是matlab开发人员),因此如果有更简单的方法,我完全支持。我只需要能够独立于matlab运行事务,但是让matlab通过Java控制这些进程。


Matlab 可以做什么?它能够处理 XML 处理吗? - skaffman
Matlab可以运行Java代码。我将编写一个Java“客户端”应用程序,该应用程序将由Matlab代码运行。 - griffin
6个回答

28
服务器监听连接。当客户端建立连接时,客户端可以发送数据。在当前示例中,客户端发送消息“Hi my server”。“bye”是客户端发送以终止连接的消息。然后服务器也发送消息“bye”。最后,连接被结束,服务器等待另一个连接。这两个程序应该在同一台机器上运行。但是,如果您想在两台不同的机器上运行它们,只需将地址“localhost”更改为将运行服务器的机器的IP地址即可。
import java.io.*;
import java.net.*;
public class Provider{
    ServerSocket providerSocket;
    Socket connection = null;
    ObjectOutputStream out;
    ObjectInputStream in;
    String message;
    Provider(){}
    void run()
    {
        try{
            //1. creating a server socket
            providerSocket = new ServerSocket(2004, 10);
            //2. Wait for connection
            System.out.println("Waiting for connection");
            connection = providerSocket.accept();
            System.out.println("Connection received from " + connection.getInetAddress().getHostName());
            //3. get Input and Output streams
            out = new ObjectOutputStream(connection.getOutputStream());
            out.flush();
            in = new ObjectInputStream(connection.getInputStream());
            sendMessage("Connection successful");
            //4. The two parts communicate via the input and output streams
            do{
                try{
                    message = (String)in.readObject();
                    System.out.println("client>" + message);
                    if (message.equals("bye"))
                        sendMessage("bye");
                }
                catch(ClassNotFoundException classnot){
                    System.err.println("Data received in unknown format");
                }
            }while(!message.equals("bye"));
        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
        finally{
            //4: Closing connection
            try{
                in.close();
                out.close();
                providerSocket.close();
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
        }
    }
    void sendMessage(String msg)
    {
        try{
            out.writeObject(msg);
            out.flush();
            System.out.println("server>" + msg);
        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
    }
    public static void main(String args[])
    {
        Provider server = new Provider();
        while(true){
            server.run();
        }
    }
}

客户端

import java.io.*;
import java.net.*;
public class Requester{
    Socket requestSocket;
    ObjectOutputStream out;
    ObjectInputStream in;
    String message;
    Requester(){}
    void run()
    {
        try{
            //1. creating a socket to connect to the server
            requestSocket = new Socket("localhost", 2004);
            System.out.println("Connected to localhost in port 2004");
            //2. get Input and Output streams
            out = new ObjectOutputStream(requestSocket.getOutputStream());
            out.flush();
            in = new ObjectInputStream(requestSocket.getInputStream());
            //3: Communicating with the server
            do{
                try{
                    message = (String)in.readObject();
                    System.out.println("server>" + message);
                    sendMessage("Hi my server");
                    message = "bye";
                    sendMessage(message);
                }
                catch(ClassNotFoundException classNot){
                    System.err.println("data received in unknown format");
                }
            }while(!message.equals("bye"));
        }
        catch(UnknownHostException unknownHost){
            System.err.println("You are trying to connect to an unknown host!");
        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
        finally{
            //4: Closing connection
            try{
                in.close();
                out.close();
                requestSocket.close();
            }
            catch(IOException ioException){
                ioException.printStackTrace();
            }
        }
    }
    void sendMessage(String msg)
    {
        try{
            out.writeObject(msg);
            out.flush();
            System.out.println("client>" + msg);
        }
        catch(IOException ioException){
            ioException.printStackTrace();
        }
    }
    public static void main(String args[])
    {
        Requester client = new Requester();
        client.run();
    }
}

ObjectI/OStream很方便,但我更喜欢使用PrintWriter和BufferedReader。我已经遇到了许多ObjectI/OStream的问题。 - Martijn Courteaux
但是我该怎么关闭客户端的连接,而其他客户端仍然可以连接到这个套接字服务器?在这个例子中,如果我收到bye消息,它会关闭客户端和服务器的连接。我只想在收到bye消息时关闭客户端连接。 - Jack Daniel

2
听起来你需要让Java服务器进程独立于Matlab进程。这样,当Matlab进程启动/停止时,Java服务器将继续运行。Java服务器将会等待传入的连接,并处理多个连接、断开等。
这里有一个编写Java套接字服务器的教程(注意它是Java客户端/服务器套接字通信的一部分)。
你将面临一个挑战(我无法帮助你,因为不了解Matlab),那就是创建或使用平台无关的方式来创建实际消息,无论是使用二进制表示、XML(看起来Matlab有一些XML功能)还是其他方式。

这正是我所想的。你知道类似的好例子吗? - griffin
首先,我建议你跟着那个教程走一遍,看看它有多直观。请注意上面的其他评论。 - Brian Agnew

2
如果您决定选择自定义套接字级协议,那么我建议您在Java端使用JBoss Netty
引用: 换句话说,Netty是一个NIO客户端服务器框架,可快速轻松地开发诸如协议服务器和客户端之类的网络应用程序。它极大地简化和简化了网络编程,如TCP和UDP套接字服务器。

2

如果你说的没错,Matlab可以在自身内部运行Java代码,那么你就可以使用RMI来在Matlab和Java服务器之间进行通信。相比于原始套接字编程,RMI要容易得多。


1

教程是易于部分:Sun's Sockets Tutorial 教会了我关于套接字编程所需的一切,希望对你也有帮助。

我认为你需要澄清自己想要支持的命令,特别是第一个和第三个:

  • 如果Java进程没有运行,谁会响应你的 startServer 命令?如果它正在运行,谁还需要它? :)

  • 你当然可以实现一个 stopServer 命令。但这有点像让你的电脑拔掉自己的电源线。我们回到之前的问题:如果服务器停止了,谁会听到启动命令?

据我理解,你只需要中间那个远程操作。

然而... 套接字编程只是比较有趣的部分。你可以考虑查看 the RMI tutorial 作为替代方案。


1

你有什么理由不能将你的Java服务器实现为Tomcat中的一组Servlet集合?Tomcat提供了所有自启动和保持服务器运行所需的工具,你可以很容易地实现SOAP服务或RESTful Web服务,这将有助于将你的Matlab代码与Java代码解耦。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接