我有TCP服务器和客户端程序。我的客户端正在向服务器发送消息,服务器正在将消息回显给客户端。
在服务器上,我想打印收到的内容,但在此之前,我想显示客户端的IP和主机名。我该怎么办?
我尝试了一些代码,但是似乎不起作用,IP显示为"0.0.0.0"
。我在UDP中有相同的程序,并且运行良好。
此外,如何打印主机名?客户端/服务器在同一台计算机上。
这是我服务器的代码(有趣的部分在最后):
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int listenSocket, status, socketClient;
unsigned short int msgLength;
struct addrinfo hints, *servinfo;
struct sockaddr_in clientAddress;
socklen_t clientAddressLength = sizeof clientAddress;
char msg[101]; //Chaque message fait 100 caractères ma
if ((listenSocket = socket(servinfo->ai_family, servinfo->ai_socktype,
servinfo->ai_protocol)) == -1) {
perror("socket:");
return 4;
if (listen(listenSocket, 5) != 0) {
printf("Erreur de listen : %s", strerror(errno));
exit(1);
}
int sizeOfSockAddr = sizeof(clientAddress);
socketClient= accept(listenSocket, NULL, NULL);
if (socketClient < 0) {
printf("error accept: %s\n",strerror(errno));
return 6;
}
// Libération de la mémoire occupée par les enregistrements
freeaddrinfo(servinfo);
printf("Attente de requête du client sur le port %s\n", argv[1]);
while (1) {
// Mise à zéro du tampon de façon à connaître le délimiteur de fin de chaîne.
memset(msg, 0, sizeof msg);
if (recv(socketClient, msg, sizeof msg, 0) == -1) {
perror("recv:");
close(listenSocket);
close(listenSocket);
return 7;
}
msgLength = strlen(msg);
if (msgLength > 0) {
printf(">> from %s", inet_ntoa(clientAddress.sin_addr));
printf(":%hu\n", ntohs(clientAddress.sin_port));
printf(" Message reçu : %s\n", msg);
}
}
}
答案 0 :(得分:2)
您有一个clientAddress
变量来保存客户端的IP和端口,甚至可以打印出来,但实际上并没有填充任何有意义的数据。
accept()
可以选择为您填充该变量:
accept(listenSocket, (struct sockaddr *)&clientAddress, &clientAddressLength);
或者,您可以改用getpeername()
:
getpeername(socketClient, (struct sockaddr *)&clientAddress, &clientAddressLength);
关于获取客户端的主机名,您可以将clientAddress
(填充后)传递给getnameinfo()
:
char hostname[NI_MAXHOST] = {};
getnameinfo((struct sockaddr *)&clientAddress, clientAddressLength, hostname, sizeof(hostname), NULL, 0, 0);
// use hostname as needed...
附带说明:
在使用getaddrinfo()
创建监听套接字时,应在AI_PASSIVE
字段中包含hints.ai_flags
标志。
由于您正在使用getaddrinfo()
处理IPv4,并且有可能稍后轻松更新以支持IPv6,因此您应该考虑从inet_ntoa()
切换到inet_ntop()
或改为使用getnameinfo(NI_NUMERICHOST)
来打印客户端的IP。 inet_ntoa()
仅支持IPv4,其他均支持IPv4和IPv6。