进程可以连接到自己创建的套接字吗?

时间:2011-11-14 06:45:00

标签: java

编辑:下面的代码不会抛出任何异常,但没有输出并挂起。它应输出“测试信息”。在main()中,我们启动一个线程,该线程在一个随机端口上监听服务器套接字。试图在同一随机端口上与ServerSocket连接和通信的主线程,但显然是失败的。为什么呢?

public class IntraProcSockTest {
private static int port;

private class Listener extends Thread {
    public Listener() {
    }

    public void run() {
        try {
            ServerSocket serverSocket = new ServerSocket(0);
            port = serverSocket.getLocalPort();
            Socket socket = serverSocket.accept();

            BufferedReader in;
            String fromClient;

            in = new BufferedReader(new InputStreamReader(
                    socket.getInputStream()));

            while ((fromClient = in.readLine()) != null) {
                System.out.println("From client: " + fromClient);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public IntraProcSockTest() {
    new Listener().start();
}

public static void main(String[] args) {
    new IntraProcSockTest();

    try {
        Thread.sleep(5000);
        Socket socket = new Socket("localhost", port);
        PrintWriter socketOut = new PrintWriter(socket.getOutputStream());

        socketOut.println("Test message");
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

2 个答案:

答案 0 :(得分:3)

进程可以连接到自己创建的套接字,没有问题。 向我们展示引发异常的代码和/或有关异常的更多详细信息。

首先,请注意为客户端套接字指定本地端口(连接到另一个正在侦听的端口)。让操作系统选择一个随机端口。请记住,任何套接字都由四个元素(remote host, local host, remote port, local port)标识,如果您在同一个本地端口上绑定服务器套接字和客户端套接字,则将其设为4498,两个套接字定义如下:(localhost, localhost, 4498, 4498)这不起作用。我怀疑这可能是你的问题 为避免此类问题,客户端套接字通常绑定到OS选择的随机端口。向我们展示您的代码,特别是创建客户端套接字并连接到服务器套接字的部分。

关于IPC,使用套接字作为进程间甚至进程内通信技术并不总是不好。显然,性能更差,并且您可能会丢失一些代码可读性,但您的软件可以轻松移植到网络(分布式)应用程序。这取决于你的计划,它不像IPC套接字==坏。

答案 1 :(得分:2)

要在一个线程中创建一个Socket连接,你可以。

ServerSocket ss = new ServerSocket(0); // open a random free port.
Socket c = new Socket(ss.getInetAddress(), ss.getLocalPort());
Socket s = ss.accept();
ss.close();

final byte[] bytes = "Hello World!".getBytes();
final OutputStream out = c.getOutputStream();
out.write(bytes.length);
out.write(bytes);


final DataInputStream in = new DataInputStream(s.getInputStream());
int len = in.read();
final byte[] b = new byte[len];
in.readFully(b);
System.out.println(new String(b));

c.close();
s.close();

如果你想要的只是一个进程中的IPC,套接字不是最快或最简单的方法。尝试使用Pipe(NIO)或PipeInput / OutputStream(IO)。它更快更简单。

Pipe pipe = Pipe.open();
SinkChannel sink = pipe.sink();
SourceChannel source = pipe.source();

PipedOutputStream output = new PipedOutputStream();
PipedInputStream input = new PipedOutputStream(output);  

BTW:您可以在同一个线程中连接客户端和服务器Socket,但

使用交换机的速度提高了10倍,使用环形缓冲区的速度再快了。

如果您想要方便,使用ExecutorService是将工作删除到后台线程池的最佳方法。这仍然可以每秒执行数百万个任务。