0

How do I setup outcoming port socket constantly in ESP32? My full program is possible to destroy socket by close and recreate new socket. But I want new socket is keep using same port number.

I'm using sendto, whenever my program send data to a target UDP server, that server is seeing it as come from random port, commonly the port value is above 50000 and increment 1 everytime I recreate new socket. How do I make my UDP client constantly like 8888 so the UDP server will see it data come from port 8888?

this is how I define my UDP socket client:

int udpSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
struct timeval timeout;
timeout.tv_sec = sec;
timeout.tv_usec = usec;
setsockopt(uwcSock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);

UDP Client: ESP32

UDP Server: <any platform, doesn't matter with question>

Update: I tried bind but the port still dynamic.


static u16_t CLNT_PORT = 8888;
static int uwcSock = 0;
struct sockaddr_in destAddr;
struct sockaddr_in clientAddr;
struct timeval timeout;

esp_err_t uwc_udp_init() {
  if (!uwcIsWifiInit) {
    return ESP_FAIL;
  }

  close(uwcSock);

  isUdpInit = false;

  destAddr.sin_addr.s_addr = inet_addr(SERV_IPV4);
  destAddr.sin_family = AF_INET;
  destAddr.sin_port = htons(SERV_PORT);

  clientAddr.sin_addr.s_addr = htonl(INADDR_ANY);
  clientAddr.sin_family = AF_INET;
  clientAddr.sin_port = htons(CLNT_PORT);

  uwcSock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
  if (uwcSock < 0) {
    ESP_LOGE(uwc_tag_udp, "Unable to create socket: errno %d", errno);
    return ESP_FAIL;
  }

  int err = bind(uwcSock, (struct sockaddr*)&clientAddr, sizeof(clientAddr));
  if (err < 0) {
    ESP_LOGE(uwc_tag_udp, "Socket unable to bind: errno %d", errno);
  }
  ESP_LOGI(uwc_tag_udp, "Socket bound, port %d", 9999);

  uwc_udp_set_timeout(1, 0);
  int opt = 1;
  setsockopt(uwcSock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
  uwc_udp_flush();
  uwc_udp_handshake();

  isUdpInit = true;

  ESP_LOGI(uwc_tag_udp, "ACK received!");
  ESP_LOGI(uwc_tag_udp, "UDP has been initialized!");
  return ESP_OK;
}
Citra Dewi
  • 213
  • 3
  • 12
  • Please clarify what environment this code is running in. Is it on Linux and you're sending packets to an ESP32? Is it MicroPython? CircuitPython? Something else? – romkey Aug 03 '22 at 16:05
  • @romkey sorry for unclarity, I update my question – Citra Dewi Aug 03 '22 at 16:11
  • 1
    Maybe you should set `SO_REUSEADDR` before you try to bind to it? – Gerhardh Aug 03 '22 at 17:13
  • 1
    You might want to read https://stackoverflow.com/questions/3229860/what-is-the-meaning-of-so-reuseaddr-setsockopt-option-linux and https://stackoverflow.com/questions/14388706/how-do-so-reuseaddr-and-so-reuseport-differ – Gerhardh Aug 03 '22 at 17:33
  • @Gerhardh, thanks finally work. So order is matter turns out – Citra Dewi Aug 03 '22 at 21:51
  • 1
    This also demonstrates why you should always return values (and error status) of your function calls. `bind` reported an error but you did not inspect what it was. – Gerhardh Aug 04 '22 at 06:38

1 Answers1

3

You have to bind your client with bind function. With this function you are able to set an IP and port for your client. Here is bind function api:
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
In sockaddr_in struct you can set your client IP and port for IPv4 and in sockaddr_in6 struct for IPv6. To use these structures in bind function, you need to cast them to sockaddr structure.

AliMo
  • 86
  • 6
  • So I need to use bind even though my full program is about UDP client. I thought so because this example (https://github.com/espressif/esp-idf/blob/36f49f361c001b49c538364056bc5d2d04c6f321/examples/protocols/sockets/udp_server/main/udp_server.c) use bind while udp client doesn't. – Citra Dewi Aug 03 '22 at 16:22
  • @CitraDewi Yes, no matter UDP or TCP. To set a certain IP and port, you should use `bind` function. [Here](https://stackoverflow.com/questions/56965615/what-exactly-bind-api-do-in-server-program) for more detail. – AliMo Aug 03 '22 at 16:35
  • can you give me simple example, I tried it but the port still dynamically change. Look my updated question. – Citra Dewi Aug 03 '22 at 16:57
  • @CitraDewi Has you problem solved or not? – AliMo Aug 04 '22 at 05:44
  • 2
    yes, your answer will be perfect if you mention `SO_REUSEADDR` too. – Citra Dewi Aug 04 '22 at 07:10