Невозможно запросить другой порт и отправить ответ пользователю - PullRequest
0 голосов
/ 07 июня 2018

Прежде всего, извините, если мой заголовок не очень хороший.Не могу придумать хорошего названия.Итак, я попытался создать приложение, которое прослушивает все пакеты на порту 27080. Затем оно отправляет эти пакеты на другой порт (где есть сервер, который отвечает), а затем отправляет этот ответ пользователю.Теперь с помощью iptables я перенаправил определенный тип пакетов (пакетов запросов) с основного порта в это приложение.Теперь, так как ответ получает пользователь, главный сервер должен быть в моем списке онлайн.Однако, как только я начинаю перенаправлять пакеты в это приложение, это не так.

Код:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>

#include <string>
#include <string.h> // memset()
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>

#include <linux/ip.h> // For ipv4 header.
#include <linux/udp.h> // For udp header.

#define PORT 27080
#define BUFF_LEN 512

void die(char * error);
void QueryServer(char * ServerIP, char * ServerPort, char * Query, int QueryLen, char * Response, int ResponseSize, int *ResponseLen);

int main() {
    // Create a UDP socket.
    int iSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (iSocket == -1) {
        die((char *) "Unable to create socket");
    }

    struct sockaddr_in sock_structure;

    memset((char *) &sock_structure, 0, sizeof(sock_structure)); // Zero out the structure.

    sock_structure.sin_family = AF_INET;
    sock_structure.sin_port = htons(PORT);
    sock_structure.sin_addr.s_addr = INADDR_ANY;

    // Bind socket to port.
    if (bind(iSocket, (struct sockaddr *) &sock_structure, sizeof(sock_structure)) == -1) {
        die((char *) "Error binding to port");
    }

    // Keep listening for data.
    struct sockaddr_in recvsock_structure;
    socklen_t recvsock_len = sizeof(recvsock_structure);

    // Declare variables for send socket.
    int send_socket;
    struct sockaddr_in send_socket_structure;

    int recv_len = 0;
    char recv_data[BUFF_LEN];

    while (true) {
        recv_len = recvfrom(iSocket, recv_data, BUFF_LEN, 0, (struct sockaddr *) &recvsock_structure, &recvsock_len);
        if (recv_len == -1) {
            die((char *) "Error recieving data");
        }

        // Query server.
        char send_data[BUFF_LEN];
        int send_data_len;
        QueryServer((char *) "SERVERIP", (char *) "SERVERPORT", recv_data, recv_len, send_data, BUFF_LEN, &send_data_len);
        //printf("Sending response to %s:%d : %s\n", inet_ntoa(recvsock_structure.sin_addr), ntohs(recvsock_structure.sin_port), send_data);
        // Send the response.
        if (sendto(iSocket, send_data, send_data_len, 0, (struct sockaddr *) &recvsock_structure, recvsock_len) == -1) {
            die((char *) "Error sending response");
        }
/*
        if (recv_len > 4) {
            switch(recv_data[4]) {
                case 'T' : { // Info query, check cache.
                    // Query server.
                    char send_data[BUFF_LEN];
                    int send_data_len;
                    QueryServer((char *) "SERVERIP", (char *) "SERVERPORT", recv_data, recv_len, send_data, BUFF_LEN, &send_data_len);
                    printf("Recieved data : %s\n", send_data);
                    // Send the response.
                    if (sendto(iSocket, send_data, send_data_len, 0, (struct sockaddr *) &recvsock_structure, recvsock_len) == -1) {
                        die((char *)"Error sending response");
                    }

                    break;
                }
                // Further : not an info query.
                case 'U' : { // PlayerList.
                    break;
                }
                case 'V' : { // Rules
                    break;
                }
                case 'W' : { // GetChallenge
                    break;
                }
                default : { // Other.

                }
            }
        }*/

        //printf("Received packet from %s:%d\n", inet_ntoa(recvsock_structure.sin_addr), ntohs(recvsock_structure.sin_port));
        //printf("Data: %s\n" , recv_data);
    }

    close(iSocket);
}

void QueryServer(char * ServerIP, char * ServerPort, char * Query, int QueryLen, char * Response, int ResponseSize, int *ResponseLen) {
    // Create socket.
    int iSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (iSocket == -1) {
        die((char *) "Unable to create socket");
    }

    // Bind socket to any port.
    struct sockaddr_in sock_structure;
    sock_structure.sin_family = AF_INET;
    sock_structure.sin_addr.s_addr = htonl(INADDR_ANY);
    sock_structure.sin_port = htons(0);

    socklen_t sock_structure_len = sizeof(sock_structure);
    if (bind(iSocket, (struct sockaddr *) &sock_structure, sock_structure_len) == -1) {
        die((char *) "Error binding to port");
    }

    // Query server.
    struct hostent * host;
    host = gethostbyname(ServerIP); // Get server ip address.

    struct sockaddr_in send_sock_structure;
    send_sock_structure.sin_family = host->h_addrtype;
    memcpy((char *) &send_sock_structure.sin_addr.s_addr, host->h_addr_list[0], host->h_length);
    send_sock_structure.sin_port = htons(atoi(ServerPort));

    if (sendto(iSocket, Query, QueryLen, 0, (struct sockaddr *) &send_sock_structure, sizeof(send_sock_structure)) == -1) {
        die((char *) "Error sending data to remote server");
    }

    struct timeval timeout;
    timeout.tv_sec = 3;
    timeout.tv_usec = 0;

    setsockopt(iSocket, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *) &timeout, sizeof(timeout));

    (*ResponseLen) = recvfrom(iSocket, Response, ResponseSize, 0, (struct sockaddr *) &sock_structure, &sock_structure_len);
    if (*ResponseLen == -1) {
        die((char *) "Error recieving data");
    }

    //printf("%s\n", Response);


    close(iSocket);
}

void die(char * error) {
    perror(error);
    exit(1);
}

Может ли кто-нибудь указать мне, что я делаю неправильно?

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