Если у вас валяется адринфо, отправьте .ai_addr
и .ai_addrlen
.
Попробуйте эти две программы:
send_sockaddr.cc:
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <cstdio>
#include <cerrno>
#include <cstdlib>
int main (int ac, char **av) {
if(ac != 3) {
fprintf(stderr, "Usage: %s hostname portnumber\n", *av);
return 1;
}
struct addrinfo *res0;
struct addrinfo hints = { AI_CANONNAME, 0, SOCK_DGRAM };
int rc = getaddrinfo(av[1], av[2], &hints, &res0);
if(rc) {
fprintf(stderr, "%s/%s: %s\n", av[1], av[2], gai_strerror(rc));
return 1;
}
char *name = res0->ai_canonname;
for(struct addrinfo *res = res0; res; res=res->ai_next) {
fprintf(stderr, "%s: %04X/%04X/%04X ", name, res->ai_family, res->ai_socktype, res->ai_protocol);
int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if(fd < 0) {
perror("socket");
continue;
}
rc = connect(fd, res->ai_addr, res->ai_addrlen);
if(rc < 0) {
perror("connect");
continue;
}
fprintf(stderr, "Connected (%d)\n", fd);
*(unsigned short*)res->ai_addr = htons(*(unsigned short*)res->ai_addr);
rc = send(fd, res->ai_addr, res->ai_addrlen, 0);
*(unsigned short*)res->ai_addr = ntohs(*(unsigned short*)res->ai_addr);
if(rc < 0) {
perror("send");
}
close(fd);
}
freeaddrinfo(res0);
}
listen_sockaddr.cc:
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <cstdio>
#include <cerrno>
#include <cstdlib>
#include <poll.h>
#include <vector>
#include <arpa/inet.h>
int main (int ac, char **av) {
if(ac != 2) {
fprintf(stderr, "Usage: %s portnumber\n", *av);
return 1;
}
struct addrinfo *res0;
struct addrinfo hints = { 0, 0, SOCK_DGRAM };
int rc = getaddrinfo(0, av[1], &hints, &res0);
if(rc) {
fprintf(stderr, "%s/%s: %s\n", av[1], av[2], gai_strerror(rc));
return 1;
}
char *name = res0->ai_canonname;
std::vector<pollfd> fds;
for(struct addrinfo *res = res0; res; res=res->ai_next) {
fprintf(stderr, "%s: ", name);
int fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
if(fd < 0) {
perror("socket");
continue;
}
rc = bind(fd, res->ai_addr, res->ai_addrlen);
if(rc < 0) {
perror("bind");
continue;
}
fprintf(stderr, "Bound (%d)\n", fd);
fds.push_back(pollfd({fd, POLLIN}));
}
freeaddrinfo(res0);
while( (rc = poll( &fds[0], fds.size(), -1)) > 0 ) {
for(size_t i = 0; i < fds.size(); ++i) {
pollfd& pfd = fds[i];
if(!pfd.revents)
continue;
pfd.revents = 0;
union {
sockaddr s;
sockaddr_in sin;
sockaddr_in6 sin6;
} u;
rc = recv(pfd.fd, &u, sizeof u, 0);
if(rc < 0) {
perror("recv");
continue;
}
fprintf(stderr, "Received %d bytes\n", rc);
char str[256];
switch(ntohs(u.s.sa_family)) {
case AF_INET:
if(inet_ntop(AF_INET, &u.sin.sin_addr, str, sizeof str)) {
fprintf(stderr, "AF_INET %s\n", str);
} else {
fprintf(stderr, "AF_INET unknown\n");
}
break;
case AF_INET6:
if(inet_ntop(AF_INET6, &u.sin6.sin6_addr, str, sizeof str)) {
fprintf(stderr, "AF_INET6 %s\n", str);
} else {
fprintf(stderr, "AF_INET6 unknown\n");
}
break;
default:
fprintf(stderr, "UNKNOWN\n");
break;
}
}
}
}