簡體   English   中英

UDP sendto和recvfrom在不同的端口上

[英]UDP sendto and recvfrom on different ports

在決定嘗試與工作中的某些設備通信之后,我試圖圍繞插座是如何工作的。 基本細節是設備使用UDP上的ModBus RTU協議。 數據表顯示設備偵聽端口2001並回復到端口2000.在嘗試查找一些示例代碼后,我找到了一個modbus庫並設法讓它與一些模擬器一起工作,其中發送和接收似乎是相同的港口。 但是,我似乎無法使用我的設備。 我認為問題與端口有關。 我看了一遍,看起來似乎沒有任何有用的東西(也許我只是沒有足夠的理解)。 這是我正在使用的代碼,有沒有人有任何指針。

//------------------------------------------------------------------------------
// Copyright (C) 2010, Raditex AB
// All rights reserved.
//
// FreeSCADA
// http://www.FreeSCADA.com
// freescada@freescada.com
//
//------------------------------------------------------------------------------

#include "modbus.h"
#include "modbus-udp.h"

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netdb.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//------------------------------------------------------------------------------
//
//
//------------------------------------------------------------------------------
int
modbus_udp_close(modbus_udp_handle_t *handle)
{
    if (handle == NULL)
        return -1;

    close(handle->sock);

    return 0;
}

//------------------------------------------------------------------------------
//
//
//------------------------------------------------------------------------------
int
modbus_udp_init(char *host, int port, modbus_udp_handle_t *handle, int delay)
{
    struct timeval timeout;

    if (handle == NULL)
        return -1;

    if ((handle->sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
    {
        snprintf(modbus_error_str, sizeof(modbus_error_str), "%s: couldn't get socket: %s",
                 __PRETTY_FUNCTION__, strerror(errno));
        return -1;
    }

    timeout.tv_sec  = delay;
    timeout.tv_usec = 0;

    if (setsockopt(handle->sock, SOL_SOCKET, SO_RCVTIMEO, (const void *)&timeout, sizeof(struct timeval)) == -1)
    {
        snprintf(modbus_error_str, sizeof(modbus_error_str), "%s: couldn't set receive timeout: %s.",
                 __PRETTY_FUNCTION__, strerror(errno));
        return -1;
    }

    /*
     if ((flags = fcntl(handle->sock, F_GETFL, 0)) == -1)
     {
     snprintf(modbus_error_str, sizeof(modbus_error_str),
     "%s: couldn't get fd option non-blocking: F_GETFL.", __PRETTY_FUNCTION__);
     return NULL;
     }

     if (fcntl(io->sock, F_SETFL, flags|O_NONBLOCK) == -1)
     {
     snprintf(modbus_error_str, sizeof(modbus_error_str),
     "%s: couldn't set option non-blocking: F_SETFL.", __PRETTY_FUNCTION__);
     return NULL;
     }
     */

    handle->saddr.sin_family = AF_INET;

    if ((handle->addr = gethostbyname(host)) == NULL)
    {
        snprintf(modbus_error_str, sizeof(modbus_error_str), "%s: couldn't get host: %s: %s",
                 __PRETTY_FUNCTION__, strerror(errno), host);
        return -1;
    }


    bcopy((char *) handle->addr->h_addr,
          (char *)&handle->saddr.sin_addr,
          handle->addr->h_length);

    handle->saddr.sin_port = htons(port);

    return 0;
}


//------------------------------------------------------------------------------
//
//
//------------------------------------------------------------------------------
int
modbus_udp_send(modbus_udp_handle_t *handle, modbus_packet_t *pkt)
{
    char buff[256];
    int len;

    if (pkt == NULL)
        return -1;

    len = modbus_packet_pack(pkt, buff, sizeof(buff));

    if (sendto(handle->sock, buff, len, 0, (struct sockaddr *)&handle->saddr, sizeof(handle->saddr)) != len)
    {
        snprintf(modbus_error_str, sizeof(modbus_error_str),
                 "%s: failed to send modbus UDP packet", __PRETTY_FUNCTION__);
        return -1;
    }

    return 0;
}

//------------------------------------------------------------------------------
//
//
//------------------------------------------------------------------------------
int
modbus_udp_recv(modbus_udp_handle_t *handle, modbus_packet_t *pkt)
{
    socklen_t fromlen;
    struct sockaddr_in caller;
    char buff[256];
    int len;

    // read UDP data
    fromlen = sizeof (caller);
    if ((len = recvfrom(handle->sock, buff, sizeof(buff), 0, (struct sockaddr *)&caller, &fromlen)) > 0)
    {
        return modbus_packet_parse(pkt, buff, len);
    }

    return -1;
}

數據表顯示設備偵聽端口2001並回復端口2000。

這意味着您需要創建一個套接字並將其bind()到端口2000上的本地IP,然后在端口2001上發送到sendto()設備的IP。您顯示的代碼根本不是調用bind() ,所以沒有recvfrom()本地端口,用於接收數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM