>

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);
    }
  }
}

  • 답변 # 1

    와이즈 비즈  변수를 사용하여 클라이언트의 IP 및 포트를 보유 할 수 있으며이를 인쇄하고 있지만 실제로 의미있는 데이터로 채우지는 않습니다.

    clientAddress  선택적으로 해당 변수를 채울 수 있습니다 :

    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 를 사용하고 있으므로

     IPv4를 처리하려면 나중에 IPv6을 지원하도록 쉽게 업데이트 할 수있는 가능성이 있으므로 getaddrinfo() 에서 전환하는 것을 고려해야합니다.  어느 inet_ntoa() 에  또는 inet_ntop()  대신 클라이언트의 IP를 인쇄 할 때. 와이즈 비즈  IPv4 만 지원하지만 다른 것은 IPv4와 IPv6을 모두 지원합니다.

    getnameinfo(NI_NUMERICHOST)

관련 자료

  • 이전 java - orgtestngtestngexception - 오이 테스트 러너를 인스턴스화 할 수 없습니다
  • 다음 exception - memcpy () - 액세스 위반 쓰기 위치