Проблема получения сокета Java / C ++ TCP - PullRequest
0 голосов
/ 25 мая 2018

У меня следующий сценарий:

Java-программа вызывает C ++-программу для захвата и возврата сетевых пакетов.Программа C ++ имеет специальные разрешения, установленные для захвата сетевых пакетов.Обе программы взаимодействуют через сокет TCP.Java-программа отправляет простую текстовую команду, чтобы сообщить программе C ++, чего она хочет.Программа на C ++ захватывает пакеты и отправляет их обратно в сокет.

Сокет успешно устанавливается, и исходная информация передается через него.Когда программа на C ++ подключает сокет, она отправляет простое «готово», чтобы программа Java знала, что она подключена и готова к работе.Затем Java-программа отправляет свою первую команду для сбора некоторых пакетов.Эти текстовые сообщения успешно отправлены и получены.

Программа C ++ захватывает пакеты и отправляет их в сокет (набор байтов).Я проверил это, увидев трафик в Wireshark.Однако Java-программа, похоже, не получает никаких этих данных, пока я не уничтожу программу C ++ с помощью Control-C.В этот момент Java-программа распечатывает данные, которые она получила (хотя, похоже, она не получила все, что было отправлено).

Я не понимаю, что, кажется, задерживает поток информации,Что мне не хватает?

ОБНОВЛЕНИЕ:

В соответствии с просьбой, я включаю ниже код C ++ и Java.

C ++: [Предлагаемый фокус на openSocket, send и capture функции]

#include <iostream>
#include <cstdlib>
#include <vector>
#include <cerrno>

#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "PacketCapture.h"

#define SNAP_SIZE 8192
#define COMMS_BUF_SIZE 256

struct capture_data
{
  int length;
  u_char* buffer;
};

bool openSocket(const std::string address, const int port);
void cleanUp(void);

int send(void *buffer, int length);
void capture(const int count, const std::string filter);

void split(char *value, const char *delimSet, std::vector<std::string> &list);

std::string printCaptureStatus(const int status);
void printPayload(const u_char *payload, int length);
void printHexASCIILine(const u_char *payload, int length, int offset);

int g_sock;
PacketCapture *g_pcap;

int main(int argc, char *argv[])
{
  if (argc != 5) {
    std::cerr << "Usage: " << argv[0] << " <address> <port> <device> <timeout>"
        << std::endl;
    std::exit(1);
  }

  std::string address = argv[1];
  int port = atoi(argv[2]);
  std::string device = argv[3];
  int timeout = atoi(argv[4]);

  std::cout << "address: " << address << std::endl;
  std::cout << "port: " << port << std::endl;
  std::cout << "device: " << device << std::endl;
  std::cout << "timeout: " << timeout << std::endl;

  g_pcap = new PacketCapture(device, SNAP_SIZE, timeout);

  if (g_pcap == NULL) {
    std::cerr << "Could not create packet capture" << std::endl;
    std::exit(1);
  }

  if (!openSocket(address, port)) {
    std::cerr << "Could not create socket" << std::endl;
    std::exit(1);
  }

  char buffer[COMMS_BUF_SIZE];
  std::vector < std::string > tokens;

  while (true) {
    memset(buffer, 0, COMMS_BUF_SIZE);
    int received = recv(g_sock, buffer, COMMS_BUF_SIZE, 0);

    if (received > 0) {
      std::cout << "received: " << buffer << std::endl;
      tokens.clear();
      split(buffer, "#\n", tokens);

      std::cout << tokens.size() << " tokens" << std::endl;
      for (std::vector<std::string>::iterator it = tokens.begin();
          it != tokens.end(); ++it) {
        std::cout << "'" << *it << "'" << std::endl;
      }

      if (tokens[0].compare("STOP") == 0) {
        std::cout << "stopping" << std::endl;
        break;
      }

      if (tokens[0].compare("CAPTURE") == 0) {
        int count = atoi(tokens[1].c_str());
        std::string filter = tokens[2];
        std::cout << "capture: count: " << count << ", filter: " << filter
            << std::endl;
        capture(count, filter);
      }
    } else {
      // TODO error condition
    }

    usleep(1000);
  }

  cleanUp();
  exit(0);
}

void cleanUp(void)
{
  g_pcap->close();
  delete g_pcap;
  close(g_sock);
}

bool openSocket(const std::string address, const int port)
{
  g_sock = 0;
  struct sockaddr_in server_addr;

  if ((g_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    std::cerr << "Socket creation error" << std::endl;
    return false;
  }

  memset(&server_addr, 0, sizeof(server_addr));
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(port);

  // Convert IPv4 and IPv6 addresses from text to binary form.
  if (inet_pton(AF_INET, address.c_str(), &server_addr.sin_addr) <= 0) {
    std::cerr << "Invalid address/ Address not supported" << std::endl;
    return false;
  }

  if (connect(g_sock, (struct sockaddr *) &server_addr, sizeof(server_addr))
      < 0) {
    std::cerr << "Connection Failed" << std::endl;
    return false;
  }

  char* ready = "READY";
  send(ready, strlen(ready));

  return true;
}

int send(void *buffer, int length)
{
  int result = send(g_sock, buffer, length, 0);

  if (result < 0) {
    std::cerr << strerror(errno) << std::endl;
  }

  return result;
}

void capture(const int count, const std::string filter)
{
  std::vector<struct capture_data> captureList;
  g_pcap->setFilter(filter);

  u_char data[SNAP_SIZE];
  int length = 0;
  int status = 0;

  for (int i = 0; i < count; i++) {
    status = g_pcap->capturePacketData(data, &length);

    std::cout << "capture: " << (i + 1) << ", status: "
        << printCaptureStatus(status) << ", length: " << length << std::endl;
    printPayload(data, length);

    if (status == 1 && length > 0) {
      struct capture_data capture;
      capture.length = length;
      capture.buffer = data;
      captureList.push_back(capture);
    }
  }

  std::cout << "capture count: " << captureList.size() << std::endl;

  // Send number of captures.
  int size = captureList.size();
  send(&size, sizeof(int));

  for (int i = 0; i < captureList.size(); i++) {
    struct capture_data capture = captureList[i];
    std::cout << "sending" << std::endl;
    // Send the capture data length.
    send(&(capture.length), sizeof(int));
    // Send capture data.
    int numSent = send(capture.buffer, capture.length);
    std::cout << "sent: " << numSent << std::endl;
  }
}

std::string printCaptureStatus(const int status)
{
  switch (status) {
    case 0:
      return "TIMEOUT";
    case 1:
      return "OK";
    case -1:
      return "ERROR";
    case -2:
      return "EOD";
    default:
      return "UNKNOWN";
  }
}

void split(char *value, const char *delimSet, std::vector<std::string> &list)
{
  char *ptr = strtok(value, delimSet);

  while (ptr != NULL) {
    list.push_back(ptr);
    ptr = strtok(NULL, delimSet);
  }
}

void printPayload(const u_char *payload, int length)
{
  int len_rem = length;
  int line_width = 16; /* number of bytes per line */
  int line_len;
  int offset = 0; /* zero-based offset counter */
  const u_char *ch = payload;

  if (length <= 0) {
    return;
  }

  /* data fits on one line */
  if (length <= line_width) {
    printHexASCIILine(ch, length, offset);
    return;
  }

  /* data spans multiple lines */
  while (true) {
    /* compute current line length */
    line_len = line_width % len_rem;
    /* print line */
    printHexASCIILine(ch, line_len, offset);
    /* compute total remaining */
    len_rem = len_rem - line_len;
    /* shift pointer to remaining bytes to print */
    ch = ch + line_len;
    /* add offset */
    offset = offset + line_width;

    /* check if we have line width chars or less */
    if (len_rem <= line_width) {
      /* print last line and get out */
      printHexASCIILine(ch, len_rem, offset);
      break;
    }
  }

  return;
}

void printHexASCIILine(const u_char *payload, int length, int offset)
{
  int i;
  int gap;
  const u_char *ch;

  /* offset */
  printf("%06x   ", offset);

  /* hex */
  ch = payload;

  for (i = 0; i < length; i++) {
    printf("%02x ", *ch);
    ch++;

    /* print extra space after 8th byte for visual aid */
    if (i == 7) {
      printf(" ");
    }
  }

  /* print space to handle line less than 8 bytes */
  if (length < 8) {
    printf(" ");
  }

  /* fill hex gap with spaces if not full line */
  if (length < 16) {
    gap = 16 - length;

    for (i = 0; i < gap; i++) {
      printf("   ");
    }
  }

  printf("   ");

  /* ASCII (if printable) */
  ch = payload;

  for (i = 0; i < length; i++) {
    if (isprint(*ch)) {
      printf("%c", *ch);
    } else {
      printf(".");
    }

    ch++;
  }

  printf("\n");
  return;
}

Java:

package xyz;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.LinkedList;
import java.util.List;

import xyz.HexDump;

public class TestCapture {

  private static final int    PORT = 9000;

  private static ServerSocket serverSocket;
  private static Socket       clientSocket;
  // private static BufferedReader input;
  private static InputStream  input;
  private static PrintWriter  output;

  public static void main(String[] args) {
    initSocket();
    process();
    close();
  }

  private static void initSocket() {
    try {
      System.out.println("waiting for connection");
      serverSocket = new ServerSocket(PORT);
      clientSocket = serverSocket.accept();

      // input = new BufferedReader(new
      // InputStreamReader(clientSocket.getInputStream()));
      input = clientSocket.getInputStream();
      output = new PrintWriter(clientSocket.getOutputStream(), true);

      // should be "READY"
      byte[] data = new byte[8192];
      receiveData(data);
      String response = new String(data);
      System.out.println(response);

      System.out.println("accepted connection");
      System.out.println("port: " + clientSocket.getPort() + ", local port: " + clientSocket.getLocalPort());
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private static void process() {
    try {
      // byte[] data = new byte[8192];

      // for (int i = 0; i < 10; i++) {
      output.println("CAPTURE#20#tcp port 61616");

      // int numBytes = receiveData(data);
      // System.out.println("received: " + numBytes);
      // System.out.println(HexDump.dump(data, numBytes, 16, true));

      List<CaptureInfo> captures = receiveData();

      System.out.println("captures: " + captures.size());

      for (int i = 0; i < captures.size(); i++) {
        CaptureInfo info = captures.get(i);
        System.out.println("capture: " + (i + 1) + ", length: " + info.length);
        System.out.println(HexDump.dump(info.data, info.length, 16, true));
      }
      // }

      output.println("STOP");
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private static int receiveData(byte[] data) {
    int numBytes = 0;

    try {
      numBytes = input.read(data);
    } catch (IOException e) {
      e.printStackTrace();
    }

    return numBytes;
  }

  private static List<CaptureInfo> receiveData() {
    List<CaptureInfo> result = new LinkedList<CaptureInfo>();
    byte[] data = new byte[8192];
    int numBytes = 0;

    while (numBytes != -1) {
      try {
        numBytes = input.read(data);
      } catch (IOException e) {
        e.printStackTrace();
      }

      if (numBytes >= 0) {
        result.add(new CaptureInfo(numBytes, data));
      } else {
        System.out.println("EOD");
      }
    }

    return result;
  }

  private static void close() {
    try {
      clientSocket.close();
      serverSocket.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private static class CaptureInfo {
    int    length;
    byte[] data;

    CaptureInfo(int length, byte[] data) {
      this.length = length;
      this.data = data;
    }
  }

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