У меня следующий сценарий:
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;
}
}
}