无法将 Azure Sphere 设备用作 TCP 客户端
Unable to use Azure Sphere device as TCP Client
github 的 Azure Sphere 示例中的 TCP Echo Server 示例效果很好,我可以使用我的 PC 或 raspberryPi 作为 TCP 客户端并与 sphere 设备上的 TCP echo 服务器通信。但是,我有一个要求,我需要将我的 Azure Sphere 设备作为 TCP 客户端。我修改了专用网络服务示例应用程序以作为客户端工作(注释掉 Echo TCP 服务器),但与 PC 上的 TCP 服务器 运行 的连接失败。 'connect' returns -1,errno 设置为 115(错误:正在进行操作)。我已经使用静态 ip 在 azure sphere 设备上配置了网络服务。我还验证了当 raspberrypi 用作客户端和 PC 作为服务器时,相同的 TCP 客户端和服务器应用程序工作正常。这是修改后的应用主文件:
#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;
}
是的,这是可能的。请确保目的地位于 AllowedConnections
下的应用程序清单中
github 的 Azure Sphere 示例中的 TCP Echo Server 示例效果很好,我可以使用我的 PC 或 raspberryPi 作为 TCP 客户端并与 sphere 设备上的 TCP echo 服务器通信。但是,我有一个要求,我需要将我的 Azure Sphere 设备作为 TCP 客户端。我修改了专用网络服务示例应用程序以作为客户端工作(注释掉 Echo TCP 服务器),但与 PC 上的 TCP 服务器 运行 的连接失败。 'connect' returns -1,errno 设置为 115(错误:正在进行操作)。我已经使用静态 ip 在 azure sphere 设备上配置了网络服务。我还验证了当 raspberrypi 用作客户端和 PC 作为服务器时,相同的 TCP 客户端和服务器应用程序工作正常。这是修改后的应用主文件:
#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;
}
是的,这是可能的。请确保目的地位于 AllowedConnections
下的应用程序清单中