我正在尝试使用libmilter开发邮件milter。因此,我必须定义一些回调函数。目前我在使用connect()函数。声明如下:
sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, struct sockaddr *hostaddr);
当客户端连接到milter时,将调用此回调。现在我想记录主机名,IP和端口。对于主机名,这很容易。但我不能让它与hostaddr合作。
我在StackOverflow上发现了一些类似的文章,但没有一个对我有用。看起来我必须将结构转换为sockaddr_in或sockaddr_in6,但是我遇到编译器问题,例如“成员访问不完整类型'struct sockaddr_in'”
这就是我的尝试:
struct sockaddr_in *sin;
struct sockaddr_in6 *sin6;
string ipandport;
switch (hostaddr->sa_family) {
case AF_INET:
sin = (struct sockaddr_in *) hostaddr;
unsigned char *ip = (unsigned char *)&sin->sin_addr.s_addr;
break;
case AF_INET6:
// TODO
break;
default:
ipandport = "unknown";
}
我从未想过如此难以得到如此微不足道的信息: - )
答案 0 :(得分:1)
IPv4的非编译测试示例。 IPv6几乎相同,只需调整使用的常量定义(阅读inet_ntop手册页)
#include <arpa/inet.h>
void print_ipv4(struct sockaddr *s)
{
struct sockaddr_in *sin = (struct sockaddr_in *)s;
char ip[INET_ADDRSTRLEN];
uint16_t port;
inet_pton (AF_INET, sin->sin_addr, ip, sizeof (ip));
port = htons (sin->sin_port);
printf ("host %s:%d\n", ip, port);
}
答案 1 :(得分:0)
我找到了不同的答案。在这里发帖后,我再次搜索,发现了这个,最终对我有用:
sfsistat mlfi_connect(SMFICTX *ctx, char *hostname, struct sockaddr *hostaddr) {
assert(ctx != NULL);
assert(hostaddr != NULL);
string ipandport;
char clienthost[NI_MAXHOST];
char clientport[NI_MAXSERV];
int result = getnameinfo(hostaddr, sizeof(*hostaddr),
clienthost, sizeof(clienthost),
clientport, sizeof (clientport),
NI_NUMERICHOST | NI_NUMERICSERV);
if(result != 0)
ipandport = "unknown";
else
{
if (hostaddr->sa_family == AF_INET)
ipandport = string(clienthost) + ":" + string(clientport);
else
ipandport = "[" + string(clienthost) + "]:" + string(clientport);
}
if (hostname == nullptr)
hostname = const_cast<char *>("unknown");
Client *con = new Client(string(hostname), ipandport);
// Store new client data
smfi_setpriv(ctx, static_cast<void *>(con));
cout << "id=" << con->getId()
<< " connect from " << con->getHostname()
<< " IP and port " << con->getIPandPort() << endl;
return SMFIS_CONTINUE;
}
答案 2 :(得分:0)
r := strings.NewReplacer(
"January", "Januar",
"February", "Februar",
"March", "März",
"April", "April",
"May", "Mai",
"June", "Juni",
"July", "Juli",
"August", "August",
"September", "September",
"October", "Oktober",
"November", "November",
"December", "Dezember", )
time := inputTime.Format("2 January 2006")
outputString := r.Replace(time)
可以从二进制转换为字符串,而不是inet_ntop
。
inet_pton
示例:
$ man inet_ntop
...
This function converts the network address structure src in the af address family into a character string. 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.
答案 3 :(得分:0)
struct sockaddr_in client, server;
SOCKET s , new_socket;
s = socket(AF_INET , SOCK_STREAM , 0 )
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
bind(s ,(struct sockaddr *)&server , sizeof(server))
//pending connection in queue is 1
listen(s , 1);
new_socket = accept(s , (struct sockaddr *)&client, &c);
printf ("client remote port: %i\n", ntohs(client.sin_port) );