Java, порты, сокеты, соединение через программу - PullRequest
2 голосов
/ 23 сентября 2011

Мне нужно передать соединение между двумя программами на разных устройствах в моей локальной сети. То есть, у меня есть устройство A, которое должно подключаться к устройству B: portX в моей локальной сети. Проблема в том, что я не могу подключить их друг к другу напрямую. Что мне нужно сделать, это подключить устройство A к серверу и подключить этот сервер к устройству B. На моем сервере я слушаю порт «portX», а когда я получаю соединение, я подключаюсь к устройству B на тот же порт. Затем я должен передать данные от А к В через сервер, но по какой-то причине устройство Б не делает то, что должно делать, когда оно получает данные (команды) от А.

Как я могу это сделать?

Вот как я пытался это сделать:

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(); } }

Спасибо заранее, Timofey

Ответы [ 2 ]

2 голосов
/ 27 сентября 2011

Я создал версию, которая использует каналы NIO.Преимущество этого подхода заключается в том, что вы можете использовать один поток для управления тем, что поступает из нескольких источников.Мне не нужно обязательно знать, что протокол между двумя службами, потому что мы просто копируем байты.Если вы хотите просто использовать обычные старые сокеты, вам потребуется использовать мьютекс и 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/>
 * /5316700/java-porty-sokety-soedinenie-cherez-programmu
 */
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);
  }
}
1 голос
/ 23 сентября 2011

Ваша проблема в том, что вы используете PrintWriter в качестве механизма пересылки. Вы читаете в символе, а затем записываете символ + символ новой строки. Попробуйте переключить его на remoteOut.print(inputChar);

Лучшим решением было бы просто прочитать символ, а затем записать его (вы можете использовать BufferedWriter). У commons-io уже есть методы копирования, которые делают подобные вещи в IOUtils

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...