Java / C ++ TCP套接字接收问题

时间:2018-05-25 18:39:21

标签: java c++ sockets

我有以下情况:

Java程序调用C ++程序来捕获和返回网络数据包。 C ++程序在其上设置了特殊权限以允许网络数据包捕获。这两个程序通过TCP套接字进行通信。 Java程序发送一个简单的文本命令来告诉C ++程序它想要什么。 C ++程序捕获数据包并将它们发送回套接字。

套接字正在成功建立,初始信息正在进行中。当C ++程序连接套接字时,它发送一个简单的“准备好”,让Java程序知道它已连接并准备就绪。然后,Java程序发送其第一个命令来收集一些数据包。这些短信已成功发送和接收。

C ++程序捕获数据包并将它们发送到套接字(字节集合)。我通过查看Wireshark的流量来验证这一点。但是,在使用Control-C终止C ++程序之前,Java程序似乎没有收到任何此类数据。此时,Java程序打印出它收到的数据(尽管它似乎没有收到所有已发送的数据)。

我不明白什么似乎阻碍了信息的流动。我错过了什么?

更新:

根据要求,我在C ++和Java代码下面包含。

C ++:[建议关注openSocketsendcapture函数

#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;
}

爪哇:

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

}

0 个答案:

没有答案