Ошибка подключения к сокету C ++ - PullRequest
1 голос
/ 23 июня 2010

EDIT

Я внес изменения в то, что увидел ниже, и это то, что у меня есть

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string>
#include <vector>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <errno.h>

using namespace std;

string buffer;
vector<string> ex;
int s;

void recvline ( int s, string* buf ) {
  char in, t;
  while ( 1 ) {
    recv ( s, &in, 1, 0 );
    *buf += in;
    if ( in == 10 ) {
      t = 1; }
    if ( t && in == 13 ) {
      break; }
    }
  }

void push ( int s, string msg ) {
  string o = msg + "\r\n";
  cout << "SENT:", o;
  send ( s, o.c_str(), o.size(), 0 );
  }

int main ( int argc, char *argv[] ) {
  if ( argc < 3 ) {
    cout << "Insufficient Arguments" << endl;
    exit ( 7 ); }
  s = socket ( AF_INET, SOCK_STREAM, IPPROTO_TCP );
  if ( s < 0 )
    exit ( 1 );
  struct hostent h = *gethostbyname ( argv[1] );
  struct sockaddr_in c;
  c.sin_family = AF_INET;
  c.sin_port = htons(atoi(argv[2]));
  c.sin_addr.s_addr = inet_addr ( h.h_addr_list[0] );
  if ( connect ( s, (struct sockaddr*)&c, sizeof c ) != 0 ) {
      cout << "Unable to connect to network" << endl;
      cout << strerror(errno) << endl;
      exit ( 2 );
  }
  push ( s, "USER LOLwat Lw lol.wat :LOLwat" );
  push ( s, "NICK LOLwat" );
  while ( true ) {
    recvline ( s, &buffer );
    cout << buffer;
    if ( buffer.substr(0,4).c_str() == "PING" )
      push ( s, "PONG " + buffer.substr(6,-2) );
    }
  }

И вот результат:

[dbdii407@xpcd Desktop]$ g++ ?.cpp -o 4096 - 
[dbdii407@xpcd Desktop]$ ./4096 irc.scrapirc.com 6667 - Unable to connect to network - Network is unreachable

Ответы [ 2 ]

3 голосов
/ 23 июня 2010

Мне кажется, проблема в том, что эта строка:

c.sin_port = htons(*argv[2]);

Не делает то, что вы думаете, что делает. argv[2] - строка, *argv[2] - первый символ строки. Таким образом, если вы передали «4567» в качестве второго аргумента командной строки, то *argv[2] будет «4» со значением ASCII 52. Это означает, что вы будете пытаться подключиться к порту 52, а не «4567», как это было бы ожидать.

Измените строку на:

c.sin_port = htons(atoi(argv[2]));

Функция atoi берет строку и преобразует ее в целое число. Таким образом, «4567» станет 4567.

Кроме того, в общем, вы должны проверять значение errno, когда вызов функции подобного типа завершается неудачно (обычно в документации сообщается, установлен ли errno и возможные значения, которые он может быть установленным). Это должно помочь дать вам некоторую подсказку в будущем.

Редактировать
Как уже отмечали другие, обязательно обращайте внимание на свои брекеты. Обычно проще, если вы просто всегда используете скобки вокруг if, while и так далее. То есть это:

if ( connect ( s, (struct sockaddr*)&c, sizeof c ) != 0 )
    cout << "Unable to connect to network" << endl;
    exit ( 2 );

полностью отличается от этого:

if ( connect ( s, (struct sockaddr*)&c, sizeof c ) != 0 ) {
    cout << "Unable to connect to network" << endl;
    exit ( 2 );
}
2 голосов
/ 23 июня 2010

Я решил полностью повторить свой ответ, отчасти из-за следующего комментария на странице gethostbyname:

gethostbyname * () и Функции gethostbyaddr * () устарели. Приложения должны использовать getaddrinfo (3) и getnameinfo (3) вместо этого.

Вот переработанная программа (немного очищенная с помощью bcpp ), основанная на использовании getaddrinfo. Я настоятельно рекомендую всегда компилировать со следующими параметрами:

 g++ -Wall -Wextra irc.cpp -o irc

Это обнаружило следующие ошибки в вашем коде:

irc.cpp: In function ‘void push(int, std::string)’:
irc.cpp:40: warning: right-hand operand of comma has no effect
irc.cpp: In function ‘int main(int, char**)’:
irc.cpp:87: warning: comparison with string literal results in unspecified behaviour

Я пошел дальше и исправил ошибки. Кроме того, постарайтесь устранить как можно больше глобальных переменных.

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string>
#include <vector>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <errno.h>

using namespace std;

string buffer;
vector<string> ex;

void recvline ( int s, string* buf )
{
    char in, t;
    while ( 1 )
    {
        recv ( s, &in, 1, 0 );
        *buf += in;
        if ( in == 10 )
        {
            t = 1;
        }
        if ( t && in == 13 )
        {
            break;
        }
    }
}


void push ( int s, string msg )
{
    string o = msg + "\r\n";
    cout << "SENT:" << o;
    send ( s, o.c_str(), o.size(), 0 );
}


int main ( int argc, char *argv[] )
{
    if ( argc < 3 )
    {
        cout << "Insufficient Arguments" << endl;
        exit ( 7 );
    }

    int s, sfd;
    struct addrinfo *result, *rp;

    s = getaddrinfo(argv[1], argv[2], NULL, &result);
    if (s != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
        exit(EXIT_FAILURE);
    }

    for (rp = result; rp != NULL; rp = rp->ai_next) {
        sfd = socket(rp->ai_family, rp->ai_socktype,
                    rp->ai_protocol);
        if (sfd == -1)
            continue;

        if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
            break;                  /* Success */

        close(sfd);
    }

    if (rp == NULL) {               /* No address succeeded */
        fprintf(stderr, "Could not connect\n");
        exit(EXIT_FAILURE);
    }

    freeaddrinfo(result);           /* No longer needed */

    push ( sfd, "USER LOLwat Lw lol.wat :LOLwat" );
    push ( sfd, "NICK LOLwat" );
    while ( true )
    {
        recvline ( sfd, &buffer );
        cout << buffer;
        if ( buffer.substr(0,4) == "PING" )
            push ( sfd, "PONG " + buffer.substr(6,-2) );
    }
}
...