UDP issue on Docker for WSL 2

Latest update (11/3/2021)

To simplify the deploying process, I try to use a docker-compose to initialize the docker environment by the following script:

version: "3.9"
services:
    nginx:
        image: alqutami/rtmp-hls
        container_name: "rtmp-nginx"
        ports:
            - "8080:8080"
            - "1935:1935"
        environment:
            - TZ=Asia/Shanghai
        depends_on:
            - "php"
        volumes:
            - ./nginx.conf:/etc/nginx/nginx.conf
            - ./html:/usr/local/nginx/html

    php:
        build: .
        container_name: "rtmp-php"
        ports:
            - "9000:9000"
            #- "9090:9090/udp"
        environment:
            - TZ=Asia/Shanghai
        volumes:
            - ./html:/var/www/html

But with this script, C++ program running in docker host can no longer bind to the 9090 port.

After hours of trying, I found that udp package can be sent from docker container to docker host without projecting.

Work around

While trying to send UDP request to Docker host, I find that sending UDP request to 127.0.0.1 doesn’t work at all. The program which means to process the UDP request can only run properly inside of the Docker container. After hours of searching and trying, I finally confirm that the issue is because of the WSL 2, but Docker.

To get the “localhost” of the Docker host (which means the WSL here), you have to run this command at PowerShell as administrator.

wsl -e ip -4 addr show dev eth0

Attachments

UDP server in C++

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

#define SERV_PORT   9999

int main()  
{
  int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
  if(sock_fd < 0)  
  {  
    perror("socket");
    exit(1);
  }  
  
  struct sockaddr_in addr_serv;
  int len;
  memset(&addr_serv, 0, sizeof(struct sockaddr_in));
  addr_serv.sin_family = AF_INET;
  addr_serv.sin_port = htons(SERV_PORT);
  addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
  len = sizeof(addr_serv);
 
  if(bind(sock_fd, (struct sockaddr *)&addr_serv, sizeof(addr_serv)) < 0)  
  {  
    perror("bind error:");
    exit(1);
  }  
  
  int recv_num;
  int send_num;
  char send_buf[20] = "i am server!";
  char recv_buf[20];
  struct sockaddr_in addr_client;
  
  while(1)  
  {  
    printf("server wait:\n");
      
    recv_num = recvfrom(sock_fd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&addr_client, (socklen_t *)&len);
      
    if(recv_num < 0)  
    {  
      perror("recvfrom error:");
      exit(1);
    }  
  
    recv_buf[recv_num] = '\0';
    printf("server receive %d bytes: %s\n", recv_num, recv_buf);
  
    send_num = sendto(sock_fd, send_buf, recv_num, 0, (struct sockaddr *)&addr_client, len);
      
    if(send_num < 0)  
    {  
      perror("sendto error:");
      exit(1);
    }  
  }  
    
  close(sock_fd);
    
  return 0;
}

UDP client in PHP

<?php
$server = '172.30.212.113';
$port = 9999;

if(!($sock = socket_create(AF_INET, SOCK_DGRAM, 0)))
{
	$errorcode = socket_last_error();
    $errormsg = socket_strerror($errorcode);
    die("Couldn't create socket: [$errorcode] $errormsg \n");
}
echo "Socket created \n";

$input = "hello!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
if( ! socket_sendto($sock, $input , strlen($input) , 0 , $server , $port))
{
	$errorcode = socket_last_error();
	$errormsg = socket_strerror($errorcode);
	die("Could not send data: [$errorcode] $errormsg \n");
}

if(socket_recv ( $sock , $reply , 2045 , MSG_WAITALL ) === FALSE)
{
	$errorcode = socket_last_error();
	$errormsg = socket_strerror($errorcode);
	
	die("Could not receive data: [$errorcode] $errormsg \n");
}
echo "Reply : $reply";

Leave a comment

Your email address will not be published. Required fields are marked *