当前位置: 首页 > 知识库问答 >
问题:

两台主机之间使用不同端口的UDP套接字通信

百里丁雨
2023-03-14

我有一个设备,可以在端口IN_PORT上监听UDP数据包,并在端口OUT_PORT上回显消息。我可以使用数据包发送者这样的测试软件与它通信

我必须编写一个C库(目前是Win32)来与设备通信。我做了几次测试,但我仍然无法通信。我的猜测是使用这个工作流程:

  1. 创建套接字
  2. 用设备地址、AF_INET系列和侦听端口(OUT_port)填充sockaddr_in结构
  3. 绑定套接字
  4. 更改sockaddr_in。sin_port和IN_port,并发送数据包(使用sendto)
  5. 等待答案(使用recvfrom)
  6. 从4开始重复

如果我用数据包发送器实用程序在本地工作(设备地址=127.0.0.1)模拟设备,这就有效了。我不能使用相同的工作流连接到远程地址,即使是在同一个子网中(例如,我的电脑地址:192.168.1.2,远程电脑地址192.168.1.5),因为我收到了WSAEADDRNOTAVAIL错误。

我已经测试了几个不同的工作流程,并在这里和那里阅读了几个关于这个主题的讨论,但是没有一个工作,非常有效。

有人能在这个问题上给我一些提示吗?

谢谢你!

混合

共有2个答案

姬选
2023-03-14

根据Remy Lebeau的提示,我更改了代码。现在它可以工作了。如果有人想看一看,发现一些弱点,或者提出改进建议,我会很高兴的(一个“刚刚工作”的代码永远不够;它还必须“发光”!)。注释标记了代码的前一个(错误的)版本。

#pragma comment (lib, "Ws2_32.lib")

#include <winsock2.h>
#include <stdlib.h>
#include <stdio.h>
#include <STRING>

#define IN_PORT 18
#define OUT_PORT 17
#define LOCAL_IP "10.0.10.108"
#define DEVICE_IP "10.0.10.104"

#define DEFAULT_BUFLEN  1024

int main(int argc, char *argv[])
{
  WSADATA wsaData;
  SOCKET sck;
  struct sockaddr_in sckAddrInfo;
  bool terminate;
  char dataBuffer[DEFAULT_BUFLEN];
  int rcvDataLength;
  int sckAddrInfoLength;

  WSAStartup(MAKEWORD(2,2), &wsaData);
  sck = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

  memset((&sckAddrInfo), 0, sizeof(sckAddrInfo));
  sckAddrInfo.sin_family = AF_INET;
  sckAddrInfo.sin_port = htons(IN_PORT);
  //sckAddrInfo.sin_addr.s_addr = inet_addr(DEVICE_IP);  // WRONG! Must bind local address
  sckAddrInfo.sin_addr.s_addr = inet_addr(LOCAL_IP);
  bind(sck, (struct sockaddr*)(&sckAddrInfo), sizeof(sckAddrInfo));

  terminate = false;
  sckAddrInfoLength = sizeof(sckAddrInfo);
  while(!terminate)
  {
    printf("Write echo request: ");
    gets(dataBuffer);

    sckAddrInfo.sin_addr.s_addr = inet_addr(DEVICE_IP); // Must set device address, too, not just output port
    sckAddrInfo.sin_port = htons(OUT_PORT);
    sendto(sck, dataBuffer, strlen(dataBuffer), 0, (struct sockaddr*)(&sckAddrInfo), sizeof(sckAddrInfo));

    memset(dataBuffer, '\0', DEFAULT_BUFLEN);

    rcvDataLength = recvfrom(sck, dataBuffer, DEFAULT_BUFLEN, 0, (struct sockaddr*)(&sckAddrInfo), &sckAddrInfoLength);

    printf("Device answer: %s\n", dataBuffer);

    if(strcmp(dataBuffer, "quit") == 0)
      terminate = true;
  }

  closesocket(sck);
  WSACleanup();

  return 0;
}
子车雅珺
2023-03-14

您的工作流程略有错误。它应该更像这样:

  1. 创建套接字
  2. 使用与设备、AF_INET系列和侦听端口 (OUT_PORT) 通信的本地网络适配器的地址填充sockaddr_in结构
  3. 绑定套接
  4. 使用设备地址更改sockaddr.sin_addr,并使用IN_PORT更改sockaddr_in.sin_port,并发送数据包(使用sendto)
  5. 等待答案(使用回复)
  6. 从 4 开始重复
 类似资料:
  • > 当同一主机上的两个进程使用网络套接字通信时,它们的套接字必须使用不同的端口吗? 我想是的,因为套接字由IP地址和端口号标识。如果进程的套接字使用相同的端口,则无法区分它们的套接字,对吗? 但是一个主机可以有多个网络接口,所以有多个IP地址。同一个主机上的多个网络接口是否可以共享一个端口,从而使两个套接字共享同一个端口? 例如,SSH本地端口转发由以下选项指定: 然后本地主机(SSH客户端运行的

  • 我正在处理一个应用程序,它将通过UDP从另一个本地服务接收RTP数据包。在协议的早期,我接收到一个带有IP地址的消息,我将从该IP地址接收这些RTP数据包,但端口号将被给出为0(零)...我将使用临时端口打开我的UDP套接字。我对给定消息的响应将包含我打开的实际端口,这样发送者就可以知道将数据包定向到哪里。 我的网络库是用实现套接字的。在哪里可以找到关于如何打开这样一个套接字而不指定非零端口(即使

  • 我已经在Minikube上部署了一个UDP套接字服务器。套接字服务绑定到端口2152。下面是description pod命令中的IP片段。 我的客户机与minikube运行在同一个VM上,无法与服务器通信。我在客户端使用服务器地址IP 172.17.0.3,端口为2152。我还尝试使用minikube IP 192.168.49.2将UDP数据从客户端发送到服务器。 请帮忙,这里有什么问题。

  • 我有2个Docker容器:App 应用程序-包含php应用程序代码的简单容器。它仅用于存储代码并将代码传递到远程Docker主机。 应用映像Dockerfile: Web服务容器,由PHP-FPM Nginx组成。 Web image Dockerfile: 我的问题:是否可以通过套接字链接Web容器和App容器? 主要原因是使用应用程序容器将更新的代码部署到远程Docker主机。使用卷/命名卷在

  • 服务器: 客户: 服务器开始侦听: 每个客户端连接将获得一个单独的套接字进行通信,所有的套接字都使用相同的服务器端TCP端口进行通信。

  • 我在 C#.net 中使用 UDP 异步套接字,我想让服务器和客户端在不同的端口进行通信以进行发送和接收, 服务器使用端口 A 发送到客户端,从具有端口 B 的客户端接收 客户端从具有端口 A 的服务器接收数据,并将数据发送到具有端口 B 的服务器 可能吗??