检查recvfrom() 中的返回地址(C UDP 套接字)

标签 c

这涉及尝试验证此 UDP 回显客户端中的 recvfrom()(函数的第五个参数)中的返回地址:

虽然我可以向服务器发送数据并正确接收返回通信,但在比较 fromAddr.sin_addr 和 echoServAddr.sin_addr 时,我在验证返回 IP 地址时遇到了问题。

这里的目标是比较sendto()中使用的结构中的地址和从recvfrom()返回的结构中的地址,以验证来自服务器的回显答复确实来自客户端的初始传输已发送(没有中间人的基本 POC)。

为了正确验证从 recvfrom() 返回的返回地址是否与 sendto() 调用中引用的传输到的地址匹配,我应该注意什么?

#include <stdio.h>      /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), sendto(), and recvfrom() */
#include <arpa/inet.h>  /* for sockaddr_in and inet_addr() */
#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <unistd.h>     /* for close() */

#define ECHOMAX 255     /* Longest string to echo */

void DieWithError(char *errorMessage);  /* External error handling function */

int main(int argc, char *argv[])
{
    int sock;                        /* Socket descriptor */
    struct sockaddr_in echoServAddr; /* Echo server address */
    struct sockaddr_in fromAddr;     /* Source address of echo */
    unsigned short echoServPort;     /* Echo server port */
    unsigned int fromSize;           /* In-out of address size for recvfrom() */
    char *servIP;                    /* IP address of server */
    char *echoString;                /* String to send to echo server */
    char echoBuffer[ECHOMAX+1];      /* Buffer for receiving echoed string */
    int echoStringLen;               /* Length of string to echo */
    int respStringLen;               /* Length of received response */

    // manage the command line arguments and errors
    if ((argc < 3) || (argc > 4)) {
        fprintf(stderr, "Usage: %s <Server IP> <Echo Word> [<Echo Port>]\n",
            argv[0]);
        exit(1);
        }
    // load servIP
    servIP = argv[1];
    // load echoString
    echoString = argv[2];
    // check echoString and error if too long
    echoStringLen = strlen(echoString);
    if (!(echoStringLen <= 255)) {
        DieWithError("BUFFER EXCEEDED ERROR");
    }
    // load port
    if (argc == 4)
        echoServPort = atoi(argv[3]);
    else
        echoServPort = 7;
    // create the socket
    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
        DieWithError("SOCKET CREATION ERROR");
    }
        /* Construct the server address structure */
        memset(&echoServAddr, 0, sizeof(echoServAddr));    /* Zero out structure */
        echoServAddr.sin_family = AF_INET;                 /* Internet addr family */
        echoServAddr.sin_addr.s_addr = inet_addr(servIP);  /* Server IP address */
        echoServAddr.sin_port   = htons(echoServPort);     /* Server port */

    // send the string
    inet_pton(AF_INET, servIP, &echoServAddr.sin_addr);
    if ((sendto(sock, echoString, strlen(echoString), 0, (struct sockaddr *)
        &echoServAddr, sizeof(echoServAddr))) < 0) {
        DieWithError("SEND ERROR");
    }
    // recieve a response
    respStringLen = recvfrom(sock, echoBuffer, sizeof(echoBuffer), 0,
        (struct sockaddr *) &fromAddr, &fromSize);
    if (respStringLen < 0) {
        DieWithError("RECV ERROR");
    }
    // print the message sent
    printf("SENT FROM CLIENT: '%s'\n", echoString);
    // print the message recieved
    echoBuffer[respStringLen] = '\0';
    printf("RECEIVED FROM SERVER: '%s'\n", echoBuffer);
    // check if from the correct server
    if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) {
        DieWithError("INVALID RETURN ADDRESS");
    }
    // close the socket
    close(sock);
    // exit the program
    exit(0);

}

最佳答案

如果传入数据包的源 IP/端口与您发送的数据包的目标 IP/端口相同,则 sin_addrsin_port echoServAddr 的字段和fromAddr应该匹配。

但这行代码并没有这样做:

if ((struct sockaddr *) &echoServAddr.sin_addr != (struct sockaddr *) &fromAddr.sin_addr) {

这是比较 echoServAddr.sin_addr地址针对 fromAddr.sin_addr地址 。因为这是两个独立的变量,所以这总是错误的。相反,您想要:

if ((echoServAddr.sin_addr.s_addr != fromAddr.sin_addr.s_addr) || 
    (echoServAddr.sin_port != fromAddr.sin_port))

关于检查recvfrom() 中的返回地址(C UDP 套接字),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52898998/

相关文章:

c - malloc内存分配

c++ - 寻找同构排列集的算法

c - 在 C 中使用指针打印数组时出现问题

c++ - 如何使用 LibSoX 混合两个 wav 文件

我可以使用 2 种语言制作 1 个程序吗?

c - 为什么这两个程序在 ANSI C 中表现不同?

c - 如何在 C 中逐字获取输入而不获取整个字符串?

c - 如何在C中处理任意数据集

c - 如何从main中的函数读取二维数组

c - 破解项目欧拉问题3,我的解决方案正确吗?