需要帮忙用C TCP端口号和IP地址 [英] Need help getting TCP port number and IP address in C

查看:216
本文介绍了需要帮忙用C TCP端口号和IP地址的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图找到一个办法让我的服务器,打印其TCP端口号和IP地址,但我怎么也得它现在是生产了错误的IP,我得到的0.0.33.32的输出。任何帮助AP preciated!

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&unistd.h中GT;
#包括LT&;&errno.h中GT;
#包括LT&;&string.h中GT;
#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>
#包括LT&; netinet / in.h中>
#包括LT&;&netdb.h中GT;
#包括LT&; ARPA / inet.h>
#包括LT&; SYS / wait.h>
#包括LT&;&signal.h中GT;
#包括LT&;&time.h中GT;#定义端口21467//该端口的用户将被连接到#定义积压10 //多少挂起的连接队列将举行无效sigchld_handler(int类型)
{
而(waitpid函数(-1,NULL,WNOHANG)大于0);
}//获取套接字地址,IPv4或IPv6:
无效* get_in_addr(结构sockaddr * SA)
{
如果(SA->上sa_family == AF_INET){
    返回及(((结构SOCKADDR_IN *)SA) - GT; sin_addr);
}返回及(((结构* sockaddr_in6的)SA) - GT; sin6_addr);
}INT主要(无效)
{
INT的sockfd,new_fd; //监听sock_fd,在new_fd新的连接
结构addrinfo中的提示,* servinfo,* P;
结构sockaddr_storage their_addr; //连接器的地址信息
socklen_t的sin_size;
结构sigaction的SA;
INT是= 1;
个char [INET6_ADDRSTRLEN]
INT RV;memset的(安培;提示,0,sizeof的提示);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; //用我的IP烧焦hname [100];
的gethostname(hname,sizeof的hname);如果((RV =的getaddrinfo(hname,PORT&放大器;提示,&放大器;!servinfo))= 0){
    fprintf中(标准错误的getaddrinfo:%S \\ n,gai_strerror(RV));
    返回1;
}
//遍历所有的结果,并结合第一个我们可以
为(P = servinfo; P!= NULL; P = P-> ai_next){
    如果((的sockfd =插座(对GT; ai_family,P-> ai_socktype,
            P-> ai_protocol))== -1){
        PERROR(服务器:套接字);
        继续;
    }    如果(setsockopt的(的sockfd,SOL_SOCKET,SO_REUSEADDR,&安培;是的,
            的sizeof(INT))== -1){
        PERROR(setsockopt的);
        出口(1);
    }    如果(绑定(的sockfd,P-> ai_addr,P-> ai_addrlen)== -1){
        接近(的sockfd);
        PERROR(服务器:绑定);
        继续;
    }    打破;
}如果(P == NULL){
    fprintf中(标准错误,服务器:无法绑定\\ n);
    返回2;
}
freeaddrinfo(servinfo); //所有这种结构完成如果(听(的sockfd,积压)== -1){
    PERROR(听);
    出口(1);
}sa.sa_handler = sigchld_handler; //获得全部死亡过程
sigemptyset(安培; sa.sa_mask);
sa.sa_flags = SA_RESTART;
如果(的sigaction(SIGCHLD,&安培; SA,NULL)== -1){
    PERROR(sigaction的);
    出口(1);
}
焦炭主机[100];
焦炭服务[20];则getnameinfo(对GT; ai_addr,P-> ai_addrlen,主机,sizeof的主机,服务sizeof的服务,0);
inet_ntop(对GT; ai_family,get_in_addr((结构sockaddr *)&P- GT; ai_addr)
        主机,主机的sizeof);的printf(服务器:有TCP端口号,%s和IP地址%S \\ N,服务,主机);的printf(服务器:等待连接... \\ n);INT的numBytes;
焦炭BUF [100];而(1){//主接受()循环
    sin_size = sizeof的their_addr;
    new_fd =接受(的sockfd,(结构sockaddr *)及their_addr,&安培; sin_size);
    如果(new_fd == -1){
        PERROR(接受);
        继续;
    }    inet_ntop(their_addr.ss_family,
        get_in_addr((结构sockaddr *)及their_addr)
        S,sizeof的S);    //则getnameinfo(get_in_addr((结构sockaddr *)及their_addr),sizeof的get_in_addr((结构sockaddr *)及their_addr),NULL,NULL,服务,sizeof的服务,0);    如果((的numBytes =的recv(new_fd,buf中,100,0))== - 1)
        PERROR(RECV);    / *如果((的numBytes =的recv(的sockfd,BUF,100,0))== -1){
    PERROR(RECV);
    出口(1);
} * /    结构TM *地方;
    焦炭toClient [50];
    的printf(服务器:接受'%s'的\\ n,BUF);
    time_t的CURTIME =时间(0);
    本地=本地时间(安培; CURTIME);
    如果(BUF [0] =='T'){
        的printf(服务器:接收到的时间要求\\ n,S);
        sprintf的(toClient,时间:%d个::%d个::%D,局域> tm_hour,局域> tm_min,局域> tm_sec); //赛格断层
        的printf(已发送具有IP地址%s和端口号码%s \\ n个时间到客户端,S,服务);
    }
    否则,如果(BUF [0] =='D'){
        的printf(服务器:接收日期的请求\\ n,S);
        sprintf的(toClient,日期:%d个::%d个::%D,1900 +局域> tm_year,1 +局域> tm_mon,局域> tm_mday);
        的printf(已发送具有IP地址%s和端口号码%s \\ n中的日期到客户端,S,服务);
    }
    其他{    }    如果((的numBytes =送(new_fd,toClient,sizeof的toClient,0))== -1){
    PERROR(发送);
    出口(1);
}
    关闭(new_fd);
    打破; //临时
}
接近(的sockfd);
返回0;
}


解决方案

问题是在你的 inet_ntop 电话:

  inet_ntop(对GT; ai_family,get_in_addr((结构sockaddr *)&P- GT; ai_addr)
          主机,主机的sizeof);

在这里,你正在使用指针 P 呼叫后

  freeaddrinfo(servinfo);

您需要复制该结构的sockaddr socklen_t的你有的getaddrinfo 在某些变量或存储结构 addrinfo中的继续使用。否则会导致不确定的行为,就像你正在经历。请记住,Valgrind是你的朋友。

I'm trying to find a way to get my server to print its TCP Port Number and IP address but how I have it right now is producing the wrong IP, I am getting an output of 0.0.33.32. Any help is appreciated!

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>

#define PORT "21467"  // the port users will be connecting to

#define BACKLOG 10   // how many pending connections queue will hold

void sigchld_handler(int s)
{
while(waitpid(-1, NULL, WNOHANG) > 0);
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
    return &(((struct sockaddr_in*)sa)->sin_addr);
}

return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(void)
{
int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;

memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP

char hname[100];
gethostname(hname, sizeof hname);

if ((rv = getaddrinfo(hname, PORT, &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype,
            p->ai_protocol)) == -1) {
        perror("server: socket");
        continue;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
            sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
        close(sockfd);
        perror("server: bind");
        continue;
    }

    break;
}

if (p == NULL)  {
    fprintf(stderr, "server: failed to bind\n");
    return 2;
}




freeaddrinfo(servinfo); // all done with this structure

if (listen(sockfd, BACKLOG) == -1) {
    perror("listen");
    exit(1);
}

sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
    perror("sigaction");
    exit(1);
}


char host[100];
char service[20];

getnameinfo(p->ai_addr, p->ai_addrlen, host, sizeof host, service, sizeof service, 0);
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
        host, sizeof host);

printf("server: has TCP port number %s and IP address %s\n", service, host); 

printf("server: waiting for connections...\n");

int numbytes;
char buf[100];

while(1) {  // main accept() loop
    sin_size = sizeof their_addr;
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
    if (new_fd == -1) {
        perror("accept");
        continue;
    }

    inet_ntop(their_addr.ss_family,
        get_in_addr((struct sockaddr *)&their_addr),
        s, sizeof s);

    //getnameinfo(get_in_addr((struct sockaddr *)&their_addr), sizeof get_in_addr((struct sockaddr *)&their_addr), NULL, NULL, service, sizeof service, 0);

    if ((numbytes = recv(new_fd, buf, 100, 0)) == -1)
        perror("recv");

    /* if ((numbytes = recv(sockfd, buf, 100, 0)) == -1) {
    perror("recv");
    exit(1);
}*/ 

    struct tm* local;
    char toClient[50];
    printf("server: received '%s'\n",buf);
    time_t curTime = time(0);
    local = localtime(&curTime);
    if(buf[0] == 't'    ){ 
        printf("server: received time request\n", s);
        sprintf(toClient, "Time: %d::%d::%d", local->tm_hour, local->tm_min, local->tm_sec);  //Seg faulting
        printf("Sent the time to the client having IP address %s and port number %s\n", s, service);
    }
    else if(buf[0] == 'd'){
        printf("server: received date request\n", s);
        sprintf(toClient, "Date: %d::%d::%d", 1900+local->tm_year, 1+local->tm_mon, local->tm_mday);
        printf("Sent the date to the client having IP address %s and port number %s\n", s, service);
    }
    else{

    }   

    if ((numbytes = send(new_fd, toClient, sizeof toClient, 0)) == -1) {
    perror("send");
    exit(1);
}
    close(new_fd);
    break; //Temporary
}


close(sockfd);
return 0;
}

解决方案

The problem is in your inet_ntop call:

inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
          host, sizeof host);

In here you are using pointer p after calling

freeaddrinfo(servinfo);

You need to copy the struct sockaddr and socklen_t you got from getaddrinfo in some variables, or store the struct addrinfo for further use. Otherwise you will cause undefined behavior, like you are now experiencing. Remember, Valgrind is your friend.

这篇关于需要帮忙用C TCP端口号和IP地址的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆