M
The question makes no sense that it's not working.== sync, corrected by elderman ==Update after codeYour mistakes are here.servlen = sizeof(tmp_addr); // видим struct sockaddr *tmp_addr и похоже это не тот размер -)
if(getsockname(sockfd, &sa, &servlen) == -1){
error("ERROR on getsockname");
}
tmp_addr_in = (sockaddr_in*)tmp_addr; // этот указатель
Watching where.inet_ntop(AF_INET, &(tmp_addr_in->sin_addr), // вот тут Вам не повезло, прога НЕ УПАЛА (а то, сами бы в отладчике нашли)
bufServerIp, INET_ADDRSTRLEN);
And they're all connected. tmp_addr_in and tmp_addr♪I guess we should just write.servlen = sizeof(sa);
if(getsockname(sockfd, &sa, &servlen) == -1){
error("ERROR on getsockname");
}
inet_ntop(AF_INET,
&((struct sockaddr_in *)&sa)->sin_addr, // видимо тут-то Вы и запутались
bufServerIp, INET_ADDRSTRLEN);
== sync, corrected by elderman ==I'll risk assuming the variable clilen not initiated before the challenge accept()♪ B http://man7.org/linux/man-pages/man2/accept.2.html It says: The addrlen argument is a value-result argument: the caller must ini‐
tialize it to contain the size (in bytes) of the structure pointed to
by addr; on return it will contain the actual size of the peer address.
So write:socklen_t clilen = (typeof(clilen))sizeof(cli_addr);
to call accept() (which may change its meaning).Besides, with "finished" socket, it doesn't matter to the client or server, it's always possible to find out as your own address (IP, port)int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
And the "vizavi" address.int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
In both cases the parameter addrlen the challenge must be initialized (a logical example, with the accept()() The size of the buffer for the address indicated *addr♪This is an example:avp@wubu:hashcode$ cat serv-ips.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE);
} while (0)
static int
makeSimpleServer (char *cport) // default port = 12345
{
int on = 1, asock = socket (AF_INET, SOCK_STREAM, 0);
if (setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0)
errExit("socket");
short port = cport? atoi(cport): 12345;
if (port < 1)
port = 12345;
struct sockaddr_in addr;
int laddr = sizeof(addr);
memset (&addr, 0, laddr);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(asock, (struct sockaddr *)&addr, laddr))
errExit("bind");
struct linger ling;
ling.l_onoff = 1;
ling.l_linger = 2; // seconds after shudown sock for deliver data
if (setsockopt(asock, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)))
errExit("linger");
if (listen(asock, 128))
errExit("listen");
return asock;
}
int
main (int ac, char *av[])
{
// port av[1] (default 12345) and INADDR_ANY
int asock = makeSimpleServer(av[1]);
int sock;
struct sockaddr inadr;
socklen_t slen = sizeof(inadr);
while ((sock = accept(asock, &inadr, &slen)) > 0) {
printf ("New connection %s:%d\n",
inet_ntoa(((struct sockaddr_in *)&inadr)->sin_addr),
ntohs(((struct sockaddr_in *)&inadr)->sin_port));
if (getpeername(sock, &inadr, &slen) == -1)
perror("getpeername");
else
printf("getpeername %s:%d\n",
inet_ntoa(((struct sockaddr_in *)&inadr)->sin_addr),
ntohs(((struct sockaddr_in *)&inadr)->sin_port));
if (getsockname(sock, &inadr, &slen) == -1)
perror("getsockname");
else
printf("getsockname %s:%d\n",
inet_ntoa(((struct sockaddr_in *)&inadr)->sin_addr),
ntohs(((struct sockaddr_in *)&inadr)->sin_port));
close(sock);
errno = 0;
}
perror("server exit");
}
avp@wubu:hashcode$ gcc serv-ips.c && ./a.out
New connection 10.3.35.78:46980
getpeername 10.3.35.78:46980
getsockname 10.3.35.78:12345
New connection 127.0.0.1:50958
getpeername 127.0.0.1:50958
getsockname 127.0.0.1:12345
^C
avp@wubu:hashcode$
In another window, I started, respectively.avp@wubu:~$ nc 10.3.35.78 12345
avp@wubu:~$ nc localhost 12345
As you can see, I'm working.UpdateI thought you had a challenge problem. inet_ntop()♪ ♪ ♪In accordance with http://man7.org/linux/man-pages/man3/inet_ntop.3.html The resulting string is
copied to the buffer pointed to by dst, which must be a non-null
pointer. The caller specifies the number of bytes available in this
buffer in the argument size.
♪ ♪ ♪ ♪ AF_INET
src points to a struct in_addr (in network byte order) which
is converted to an IPv4 network address in the dotted-decimal
format, "ddd.ddd.ddd.ddd". The buffer dst must be at least
INET_ADDRSTRLEN bytes long.
The example code should include:char buf[64];
inet_ntop(AF_INET,
&((struct sockaddr_in *)&inadr)->sin_addr,
buf, sizeof(buf) - 1)
I checked, the results are exactly the same as the call. inet_ntoa(...)