Невозможно использовать устройство Azure Sphere в качестве клиента TCP - PullRequest
0 голосов
/ 23 марта 2020

Образец TCP Echo Server из Azure Sphere Samples на github отлично работает, и я могу использовать мой P C или raspberryPi в качестве TCP-клиента и общаться с эхо-сервером TCP на сферном устройстве. Однако у меня есть требование, когда мне нужно мое Azure устройство Sphere в качестве TCP-клиента. Я изменил пример приложения для служб частной сети, чтобы он работал как клиент (закомментированный Echo TCP Server), но соединение с сервером TCP, работающим на P C, не удается. «Connect» возвращает -1 с ошибкой, установленной на 115 (ОШИБКА: выполняется операция). Я настроил сетевые сервисы на azure сферном устройстве со stati c ip Я также проверил, что одно и то же клиентское и серверное приложение TCP работает нормально, когда raspberrypi используется в качестве клиента, а P C в качестве сервера. Это модифицированный основной файл приложения:

#include <errno.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "applibs_versions.h"
#include <applibs/log.h>
#include <applibs/networking.h>
#include <hw/sample_hardware.h>

typedef enum {
    ExitCode_Success = 0,

    ExitCode_TermHandler_SigTerm = 1,

    ExitCode_StoppedHandler_Stopped = 2,

    ExitCode_CheckStatus_SetInterfaceState = 3,
    ExitCode_CheckStatus_GetInterfaceCount = 4,
    ExitCode_CheckStatus_GetInterfaceConnectionStatus = 5,

    ExitCode_ConfigureStaticIp_IpConfigApply = 6,
    ExitCode_StartSntpServer_StartSntp = 7,
    ExitCode_StartDhcpServer_StartDhcp = 8,

    ExitCode_TimerHandler_Consume = 9,

    ExitCode_InitLaunch_Epoll = 10,
    ExitCode_InitLaunch_Timer = 11,

    ExitCode_Main_WaitCallFailure = 12,

    ExitCode_EchoStart_Listen = 13,

    ExitCode_OpenIpV4_Socket = 14,
    ExitCode_OpenIpV4_SetSockOpt = 15,
    ExitCode_OpenIpV4_Bind = 16
} ExitCode;

int tcp_client(void);
static bool isNetworkStackReady = false;
static volatile sig_atomic_t exitCode = ExitCode_Success;

static struct in_addr localServerIpAddress;
static struct in_addr subnetMask;
static struct in_addr gatewayIpAddress;
static const uint16_t LocalTcpServerPort = 11000;
static int serverBacklogSize = 3;
static const char NetworkInterface[] = "eth0";

int tcp_client(void) {

    int sock = 0, valread;
    struct sockaddr_in serv_addr;
    char* hello = "Hello from client";
    char buffer[1024] = { 0 };
    if ((sock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0)
    {
        Log_Debug("\n Socket creation error \n");
        return -1;
    }
    Log_Debug("TCP_CLIENT: socket created\n");

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(8080);

    if (inet_pton(AF_INET, "169.254.57.67", &serv_addr.sin_addr) <= 0)
    {
        Log_Debug("\nInvalid address/ Address not supported \n");
        return -1;
    }
    Log_Debug("TCP_CLIENT: ip assigned\n");
    int conn = connect(sock, (struct sockaddr*) & serv_addr, sizeof(serv_addr));
    Log_Debug("TCP_CLIENT: conn = %d\n", conn);
    Log_Debug("ERROR: %s\n", strerror(errno));
    if (conn < 0)
    {
        Log_Debug("\nConnection Failed \n");
        return -1;
    }
    send(sock, hello, strlen(hello), 0);
    Log_Debug("Hello message sent\n");
    valread = read(sock, buffer, 1024);
    Log_Debug("%s\n", buffer);
    return 0;
}

static ExitCode CheckNetworkStatus(void)
{
    int result = Networking_SetInterfaceState(NetworkInterface, true);
    if (result != 0) {
        if (errno == EAGAIN) {
            Log_Debug("INFO: The networking stack isn't ready yet, will try again later.\n");
            return ExitCode_Success;
        } else {
            Log_Debug(
                "ERROR: Networking_SetInterfaceState for interface '%s' failed: errno=%d (%s)\n",
                NetworkInterface, errno, strerror(errno));
            return ExitCode_CheckStatus_SetInterfaceState;
        }
    }
    Log_Debug("INFO: CheckNetworkStatus: Network stack is ready\n");
    isNetworkStackReady = true;

    ssize_t count = Networking_GetInterfaceCount();
    if (count == -1) {
        Log_Debug("ERROR: Networking_GetInterfaceCount: errno=%d (%s)\n", errno, strerror(errno));
        return ExitCode_CheckStatus_GetInterfaceCount;
    }
    Log_Debug("INFO:CheckNetworkStatus: Networking_GetInterfaceCount: count=%zd\n", count);

    // Read current status of all interfaces.
    size_t bytesRequired = ((size_t)count) * sizeof(Networking_NetworkInterface);
    Networking_NetworkInterface *interfaces = malloc(bytesRequired);
    if (!interfaces) {
        abort();
    }

    ssize_t actualCount = Networking_GetInterfaces(interfaces, (size_t)count);
    if (actualCount == -1) {
        Log_Debug("ERROR: Networking_GetInterfaces: errno=%d (%s)\n", errno, strerror(errno));
    }
    Log_Debug("INFO: Networking_GetInterfaces: actualCount=%zd\n", actualCount);

    for (ssize_t i = 0; i < actualCount; ++i) {
        Log_Debug("INFO: interface #%zd\n", i);

        Log_Debug("INFO:   interfaceName=\"%s\"\n", interfaces[i].interfaceName);

        Log_Debug("INFO:   isEnabled=\"%d\"\n", interfaces[i].isEnabled);
        Networking_IpType ipType = interfaces[i].ipConfigurationType;
        const char *typeText;
        switch (ipType) {
        case Networking_IpType_DhcpNone:
            typeText = "DhcpNone";
            break;
        case Networking_IpType_DhcpClient:
            typeText = "DhcpClient";
            break;
        default:
            typeText = "unknown-configuration-type";
            break;
        }
        Log_Debug("INFO:   ipConfigurationType=%d (%s)\n", ipType, typeText);
        Networking_InterfaceMedium_Type mediumType = interfaces[i].interfaceMediumType;
        const char *mediumText;
        switch (mediumType) {
        case Networking_InterfaceMedium_Unspecified:
            mediumText = "unspecified";
            break;
        case Networking_InterfaceMedium_Wifi:
            mediumText = "Wi-Fi";
            break;
        case Networking_InterfaceMedium_Ethernet:
            mediumText = "Ethernet";
            break;
        default:
            mediumText = "unknown-medium";
            break;
        }
        Log_Debug("INFO:   interfaceMediumType=%d (%s)\n", mediumType, mediumText);

        Networking_InterfaceConnectionStatus status;
        int result = Networking_GetInterfaceConnectionStatus(interfaces[i].interfaceName, &status);
        if (result != 0) {
            Log_Debug("ERROR: Networking_GetInterfaceConnectionStatus: errno=%d (%s)\n", errno,
                      strerror(errno));
            return ExitCode_CheckStatus_GetInterfaceConnectionStatus;
        }
        Log_Debug("INFO:   interfaceStatus=0x%02x\n", status);
    }

    free(interfaces);

    return ExitCode_Success;
}

static ExitCode ConfigureNetworkInterfaceWithStaticIp(const char *interfaceName)
{
    Networking_IpConfig ipConfig;
    Log_Debug("INFO: ConfigureNetworkInterfaceWithStaticIp: %s.\n", interfaceName);
    Networking_IpConfig_Init(&ipConfig);
    inet_aton("169.254.57.70", &localServerIpAddress);
    inet_aton("255.255.0.0", &subnetMask);
    inet_aton("0.0.0.0", &gatewayIpAddress);
    Networking_IpConfig_EnableStaticIp(&ipConfig, localServerIpAddress, subnetMask,
                                       gatewayIpAddress);

    int result = Networking_IpConfig_Apply(interfaceName, &ipConfig);
    Networking_IpConfig_Destroy(&ipConfig);
    if (result != 0) {
        Log_Debug("ERROR: Networking_IpConfig_Apply: %d (%s)\n", errno, strerror(errno));
        return ExitCode_ConfigureStaticIp_IpConfigApply;
    }
    Log_Debug("INFO: Set static IP address on network interface: %s.\n", interfaceName);

    return ExitCode_Success;
}


static ExitCode init_nw_services(void)
{
    // Check the network stack readiness and display available interfaces when it's ready.
    Log_Debug("INFO: Inside init_nw_services\n");
    ExitCode localExitCode = CheckNetworkStatus();
    if (localExitCode != ExitCode_Success) {
        return localExitCode;
    }

    if (isNetworkStackReady) {
        Log_Debug("INFO: init_nw_services: The network stack is ready, so unregister the timer event handler and launch servers.\n");
        localExitCode = ConfigureNetworkInterfaceWithStaticIp(NetworkInterface);

    }

    return ExitCode_Success;
}

static ExitCode initialize_nw(void)
{
    while (!isNetworkStackReady) {
        if (!isNetworkStackReady) {
            Log_Debug("INFO: init_nw_services\n");
            ExitCode localExitCode = init_nw_services();
            if (localExitCode != ExitCode_Success) {
                exitCode = localExitCode;
                return;
            }
        }
        else {
            Log_Debug("INFO: Network stack is ready\n");


        }
    }
    Log_Debug("INFO: Initialization and server launch complete\n");
    return ExitCode_Success;
}


int main(int argc, char *argv[])
{
    Log_Debug("INFO: Private Ethernet TCP server application starting.\n");
    exitCode = initialize_nw();
    if (isNetworkStackReady)
        tcp_client();

    Log_Debug("INFO: Application exiting.\n");
    return exitCode;
}

1 Ответ

1 голос
/ 23 апреля 2020

Да, это возможно. Убедитесь, что пункт назначения указан в манифесте приложения в разделе AllowedConnections

.
...