Java、端口、套接字、通过程序管道连接

标签 java sockets port

我需要在 LAN 中不同设备上的两个程序之间建立管道连接。即,我的 LAN 中的设备 A 应连接到设备 B:portX。问题是我无法将它们直接连接起来。我要做的就是让设备 A 连接到服务器,然后让该服务器连接到设备 B。在我的服务器上,我监听端口“portX”,当我获得连接时,我连接到设备 B相同的端口。然后我必须通过服务器将数据从 A 传输到 B,但由于某种原因,设备 B 在从 A 接收到数据(命令)时没有执行其应该执行的操作。

我该怎么做?

这是我一直在尝试执行此操作的方法:

public class Main {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(8000);
        } catch (IOException e) {
            System.err.println("Could not listen on port: 8000.");
            System.exit(1);
        }
        Socket clientSocket = null;
        try {
            clientSocket = serverSocket.accept();
            System.err.println("connection accepted");
        } catch (IOException e) {
            System.err.println("Accept failed.");
            System.exit(1);
        }
        Socket remoteSocket = null;
        try {
            remoteSocket = new Socket("192.168.1.74", 8000);
        } catch (Exception e) {
            System.out.println("Failed to connect to device B");
        }
        PrintWriter remoteOut = new PrintWriter(remoteSocket.getOutputStream(),
                true);
        BufferedReader remoteIn = new BufferedReader(new InputStreamReader(
                remoteSocket.getInputStream()));
        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(new InputStreamReader(
                clientSocket.getInputStream()));
        String inputLine;
        System.out.println("Hi, we are before the while");
        int inputChar = 0;
        while ((inputChar = in.read()) >= 0) {
            remoteOut.println(inputChar);
            System.out.println(inputChar);
        }
        System.out.println("We are after the while");
        out.close();
        in.close();
        remoteIn.close();
        remoteOut.close();
        clientSocket.close();
        serverSocket.close();
        remoteSocket.close();
    }
}

提前致谢, 蒂莫菲

最佳答案

我创建了一个使用 NIO channel 的版本。这种方法的好处是您可以使用单个线程来管理来自多个源的内容。我不一定需要知道两个服务之间的协议(protocol)是什么,因为我们只是复制字节。如果您只想使用普通的旧套接字,则需要使用互斥体和 2 个线程在两个套接字之间读取/写入数据(套接字不是线程安全的)。

注意:处理错误情况可能有比仅删除连接并创建新连接更好的方法。

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Set;

/**
 * Socket Gateway for SO Question 7528528
 * User: jhawk28
 * Date: 9/26/11
 * Time: 9:03 PM
 * <p/>
 * http://stackoverflow.com/questions/7528528/java-ports-sockets-piping-a-connection-through-a-programme
 */
public class Gateway
{
  public static void main(String[] args) throws IOException
  {
    // Set up Server Socket and bind to the port 8000
    ServerSocketChannel server = ServerSocketChannel.open();
    SocketAddress endpoint = new InetSocketAddress(8000);
    server.socket().bind(endpoint);

    server.configureBlocking(false);

    // Set up selector so we can run with a single thread but multiplex between 2 channels
    Selector selector = Selector.open();
    server.register(selector, SelectionKey.OP_ACCEPT);


    ByteBuffer buffer = ByteBuffer.allocate(1024);

    while (true)
    {
      // block until data comes in
      selector.select();

      Set<SelectionKey> keys = selector.selectedKeys();

      for (SelectionKey key : keys)
      {
        if (!key.isValid())
        {
          // not valid or writable so skip
          continue;
        }

        if (key.isAcceptable())
        {
          // Accept socket channel for client connection
          ServerSocketChannel channel = (ServerSocketChannel) key.channel();
          SocketChannel accept = channel.accept();
          setupConnection(selector, accept);
        }
        else if (key.isReadable())
        {
          try
          {
            // Read into the buffer from the socket and then write the buffer into the attached socket.
            SocketChannel recv = (SocketChannel) key.channel();
            SocketChannel send = (SocketChannel) key.attachment();
            recv.read(buffer);
            buffer.flip();
            send.write(buffer);
            buffer.rewind();
          } catch (IOException e)
          {
            e.printStackTrace();

            // Close sockets
            if (key.channel() != null)
              key.channel().close();
            if (key.attachment() != null)
              ((SocketChannel) key.attachment()).close();
          }
        }
      }

      // Clear keys for next select
      keys.clear();
    }
  }

  public static void setupConnection(Selector selector, SocketChannel client) throws IOException
  {
    // Connect to the remote server
    SocketAddress address = new InetSocketAddress("192.168.1.74", 8000);
    SocketChannel remote = SocketChannel.open(address);

    // Make sockets non-blocking (should be better performance)
    client.configureBlocking(false);
    remote.configureBlocking(false);

    client.register(selector, SelectionKey.OP_READ, remote);
    remote.register(selector, SelectionKey.OP_READ, client);
  }
}

关于Java、端口、套接字、通过程序管道连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7528528/

相关文章:

sockets - 所有端口都执行相同的工作?

Java的UTF-8编码

java - 无法导入 javax.ejb.Schedules 和 javax.ejb.Schedule 注释

java - 如何有效实现数据库功能?

Java使用beta分布生成0到1的随机数

javascript - 浏览器中的客户端服务器?

java - 根据时间戳对来自不同客户端的请求进行排序

java - Android 中的 Socket.read() 关闭时不返回任何内容并且不会抛出异常

linux - 审计 Linux 上打开/关闭的端口

sockets - 如何使用 SBCL 的套接字重用之前打开的端口?