2016-03-28 51 views
-1

我正在研究连接到主机和端口的聊天bot。虽然,任何时候我连接到除“1234”以外的任何端口,我都会收到connect: Connection refused错误。这似乎是由套接字造成的,为什么它只连接到单端口的任何想法?连接拒绝连接到除1234以外的任何端口

#include <stdio.h> 
//#include "parse.h" 
#include <netdb.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/socket.h> 
#include <sys/un.h> 
#include <stdlib.h> 

int choice(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, 
     struct timeval *timeout) { 
    int n = select(nfds, readfds, writefds, exceptfds, timeout); 
    if (n < 0) { 
     perror("select"); 
     exit(1); 
    } 
    return(n); 
} 

int main(int argc, char **argv) { 
    if (argc < 2) { 
     fprintf(stderr, "usage: %s hostname [port number] ...\n", argv[0]); 
     return(1); 
    } 

    int sockfd; 
    char buf[500]; 
    struct hostent *hp; 
    struct sockaddr_in peer; 
    fd_set master; 
    peer.sin_family = AF_INET; 

    if (argc == 2) { 
     peer.sin_port = htons(1234); 
    } else { 
     peer.sin_port = htons(atoi(argv[2])); 
    } 


    //HOST 
    if ((hp = gethostbyname(argv[1])) == NULL) { 
     fprintf(stderr, "%s: no such host\n", argv[1]); 
     return(1); 
    } 

    if (hp->h_addr_list[0] == NULL || hp->h_addrtype != AF_INET) { 
     fprintf(stderr, "%s: not an internet protocol host name\n", argv[1]); 
     return(1); 
    } 

    //SOCKET 
    sockfd = socket(AF_INET, SOCK_STREAM, 0); 
    if (connect(sockfd, (struct sockaddr *)&peer, sizeof(peer)) == -1) { 
     perror("connect"); 
     close(sockfd); 
     exit(1); 
    } 

    FD_ZERO(&master); 
    FD_SET(STDIN_FILENO, &master); 
    FD_SET(sockfd, &master); 
    fd_set fds = master; 

    //LOOP 
    while(1) { 
     choice(sockfd+1, &fds ,NULL,NULL,NULL); 
     if(FD_ISSET(STDIN_FILENO, &fds)) { 
      fgets(buf, sizeof buf, stdin); 
      if (strlen(buf) > 0) { 
       printf("success"); 
       /* 
       struct expr *e = parse(buf); 
       if (e) { 
        printf("Hey XXX, %d\n", evalexpr(e)); 
        freeexpr(e); 
       } else { 
        printf("Hey XXX, I don't like that.\n[%s]\n", errorstatus); 
       } */ 
      } 
     } 
    } 
} 

我注释了一段代码,它需要额外的代码才能保持代码最小和可复制(?)。我应该可以连接到端口,如1235,20000,25000等。

+2

您应该能够连接到处于LISTEN状态的任何端口。不只是任何旧港口。 – EJP

+1

'select()'修改传递给它的'fd_set'变量,所以你需要在每次循环迭代中重置'fds'变量。在Linux上,'select()'也会修改'timeval'变量,如果传入的话,所以你必须重置它(如果你使用的话)。 –

+0

我不喜欢这个问题,因为它使用了一个函数,每一份体面的文档都清楚地陈述了**弃用的**,而是支持一种替代方案,它使得协议无关的通信(例如,在没有修改的情况下在IPV4和IPV6上工作),但是更重要的是**更清洁,更易于使用**,并可能使错误像拇指一样突出。 – Sebivor

回答

1

您正在查找主机名,但您永远不会将生成的IP地址转换为peer,因此您并未实际连接到主机。您需要添加:

peer.sin_addr = *((struct in_addr*)(hp->h_addr_list[0])); 
+1

虽然在技术上是正确的,但请注意''gethostbyname()'已弃用,您应该使用'getaddrinfo()'来代替。它返回'sockaddr_in'和/或'sockaddr_in6'对象的链表(取决于你所要求的),它可以按原样传递给'connect()'。循环访问列表,直到其中一个地址成功或列表已用尽。 –

+0

@RemyLebeau感谢您的编辑。我没有写关于'gethostname()'的任何信息。推测你的评论是针对OP的? – EJP

相关问题