Socket dual client/server Linux

I'm trying to make a "dual/server client" (ipv4,ipv6) with sockets in linux but i don't know how to join both codes. I have a dual client ipv4 and ipv6, but i have problems with the server if you notice the only difference between them it's the AF_INET (pf_inet ipv4, and if_inet6 ipv6) and the port of the server (1234 ipv4, 5678 ipv6). I need help how i can do a program that can connect hear ipv4 and ipv6 in the same port at the same time (dual stack)?

Ipv4 server:

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

char *
addrtype(int addrtype)
{
switch(addrtype) {
case AF_INET:
return "AF_INET";
case AF_INET6:
return "AF_INET6";
}
return "Unknown";
}
int
abrir()
{
int escuchafd = 0;
struct sockaddr_in sin;
escuchafd = socket (AF_INET, // Internet IPv4
SOCK_STREAM, // TCP
0);
if (escuchafd == -1)
{
perror ("No se pudo abrir el socket");
exit(-1);
}
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(1234);
if (bind(escuchafd, (struct sockaddr*)&sin, sizeof(sin)) ==-1)
{
perror("No se pudo hacer la asociación (bind)");
exit(-1);
}
return escuchafd;
}
void
print_addr(struct sockaddr_in *addr)
{
char host[512];
printf ("\tFamily:%s\n", addrtype(addr->sin_family));
printf ("\tPort: %d\n", ntohs(addr->sin_port));
printf ("\tIP Address: %s\n", inet_ntoa(addr->sin_addr));
int res = getnameinfo((const struct sockaddr *)(addr),
(socklen_t) sizeof(*addr),
host,
512,
NULL,
0, 0);
if (res == 0)
printf ("\tHostname: %s\n", host);
}
void
echo(int confd)
{
char msg[1024];
char snt[1024];
int res = 0;
while (res == 0)
{
bzero(msg, 1024);
if (read(confd, msg, 1024)>0)
printf ("CLI: %s", msg);
if (strncmp(msg, ".", 1) == 0)
res = 1;
else
{
strcpy(snt, "SRV: ");
strcat(snt, msg);
write(confd, snt, strlen(snt));
}
}
}
void
atender(int escuchafd)
{
struct sockaddr_in cli;
int confd;
socklen_t slen; // for (;;)
{
slen = sizeof(cli);
confd = accept(escuchafd, (struct sockaddr*)&cli, &slen);
if (confd == -1)
{
perror("No se pudo establecer la conexión (accept)");
exit(-1);
}
printf ("Conexión establecida: \n");
print_addr(&cli);
echo (confd);
}
}
int
main()
{
int escuchafd = 0;
escuchafd = abrir();
if (listen(escuchafd, 5) == -1)
{
perror ("No se pudo poner en escucha (listen)");
exit(-1);
}
atender(escuchafd);
close(escuchafd);
exit(0);
}

Ipv6 server:

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

char *
addrtype(int addrtype)
{
switch(addrtype) {
case AF_INET:
return "AF_INET";
case AF_INET6:
return "AF_INET6";
}
return "Unknown";
}
int
abrir()
{
int escuchafd = 0;
struct sockaddr_in6 sin;
escuchafd = socket (AF_INET6, // Internet IPv6
SOCK_STREAM, // TCP
0);
if (escuchafd == -1)
{
perror ("No se pudo abrir el socket");
exit(-1);
}
bzero(&sin, sizeof(sin));
sin.sin6_family = AF_INET6;
sin.sin6_port = htons(5678);
sin.sin6_addr= in6addr_any;
sin.sin6_flowinfo = 0;
if (bind(escuchafd, (struct sockaddr*)&sin, sizeof(sin)) ==-1)
{
perror("No se pudo hacer la asociación (bind)");
exit(-1);
}
return escuchafd;
}
void
print_addr(struct sockaddr_in6 *addr)
{
char host[512];
bzero(host, 512);
inet_ntop(AF_INET6,
(const void*)&(addr->sin6_addr),
host,
512
);
printf ("\tFamily: %s\n", addrtype(addr->sin6_family));
printf ("\tPort: %d\n", ntohs(addr->sin6_port));
printf ("\tIP Address: %s\n", host);
bzero(host, 512);
int res = getnameinfo((const struct sockaddr *)(addr),
(socklen_t) sizeof(*addr),
host,
512,
NULL,
0, 0);
if (res == 0)
printf ("\tHostname: %s\n", host);
}
void
echo(int confd)
{
char msg[1024];
char snt[1024];
int res = 0;
while (res == 0)
{
bzero(msg, 1024);
if (read(confd, msg, 1024)>0)
printf ("CLI: %s", msg);
if (strncmp(msg, ".", 1) == 0)
res = 1;
else
{
strcpy(snt, "SRV: ");
strcat(snt, msg);
write(confd, snt, strlen(snt));
}
}
}
void
atender(int escuchafd)
{
struct sockaddr_in6 cli;
int confd;
socklen_t slen; // for (;;)
{
slen = sizeof(cli);
confd = accept(escuchafd, (struct sockaddr*)&cli, &slen);
if (confd == -1)
{
perror("No se pudo establecer la conexión (accept)");
exit(-1);
}
printf ("Conexión establecida: \n");
print_addr(&cli);
echo (confd);
}
}
int
main()
{
int escuchafd = 0;
escuchafd = abrir();
if (listen(escuchafd, 5) == -1)
{
perror ("No se pudo poner en escucha (listen)");
exit(-1);
}
atender(escuchafd);
close(escuchafd);
exit(0);
}

IPV4 clients and servers can talk to IPV6 clients and servers if they can resolve the address and port. So, an IPV4 server is already dual accessible but a high IPV6 server might be inaccessible to an IPV4 client. If the server is using inetd, it does not have to deal with IPV6/4. inetd code shows how to be a dual server.

I know, the Ipv4 server only hear's Ipv4 clients and it's the same with ipv6 server that only can talk with ipv6 client's. Thats it's why I want more information or help to become the ipv6 server in a dual server, but i don't know how. But thanks I'm wonna read inetd code

IPV6 clients can use low ip/port IPV4 servers, and IPV4 cients can use low ip/port IPV6 servers as long as there is a dual IP stack on the server and dual net fabric between. Remember that, on a client or server, a connection just devolves into an open socket fd. If I am listening on or connecting to port 80 TCP, I never know which stack my connection came from.