C ++ сеть, recv () не работает без причины (?) - PullRequest
0 голосов
/ 26 августа 2018

Я пишу чат-сервер на с ++ для собственного удовольствия, но я довольно плохо знаком с сетью в целом. Мои знания получены из руководства Биджа этого сайта и подхода сверху вниз от Kurose & Ross.

Моя проблема в том, что я написал код, похожий на тот, который вы можете найти по ссылке, но он не работает. Программа не работает, когда я пытаюсь использовать функцию recv () на сервере.

Я знаю, что recv () может вернуть любое количество байтов, но это просто дает мне -1. Я знаю, что мне нужен цикл, чтобы собрать воедино отправляемое сообщение, но пока ничего такого нет. Однако send () в клиенте говорит, что отправил сумму, указанную в буфере (да, я знаю, что это, вероятно, избыточно, хотя и не уверен, что это ошибка).

Мне кажется, что сервер ... как-то закрыт? Я почти уверен, что где-то напутал, есть определенная строка кода, в которой я действительно не уверен (см. Комментарий). Мне удалось заставить его работать вчера, но после этого что-то пошло не так.

Я действительно новичок в программировании сокетов и любых видах сетей в целом, но вызовы функций и тому подобное взяты из руководств, у меня есть догадка, проблема будет в той части, где я указываю порты и адреса, может быть, байты не приходят на сервер, потому что я отправляю их куда-то еще? Но если accept () работает, разве это не означает, что TCP-соединение сформировано, разве я не смогу использовать его после этого?

Я использую Lubuntu linux, последний выпуск, если это поможет.

Если вы обнаружите проблему, подскажите, пожалуйста, как это правильно сделать? В любом случае, вот код сервера:

void start() {

    char message[1024] = "";

    int socketfd = socket( AF_INET, SOCK_STREAM, 0 ), opt = 1, new_socket;

    struct sockaddr_in address;
    struct sockaddr_storage cl_addr;
    socklen_t len = sizeof(address);

    if( socketfd != 0 ) {

        address.sin_family = AF_INET;
        address.sin_port = htons( PORT );
        address.sin_addr.s_addr = INADDR_ANY;

        if( setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(int)) < 0 ) {
            perror("Setsockopt failed");
            exit(EXIT_FAILURE);
        }

        if( bind( socketfd, (struct sockaddr*)&address, len ) < 0 ) {           
            perror("Couldn't bind to port");
            exit(EXIT_FAILURE);
        } 

        if( listen( socketfd, 3 ) < 0 ) {
            perror("Listening on port failed");
            exit(EXIT_FAILURE);
        }

        if( (new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len  ) < 0) ) {
            perror("Couldn't accept request");
            exit(EXIT_FAILURE);
        }

        /// This is where it fails
        std::cout << recv( new_socket, message, 1024, 0) <<  std::endl;
        close(new_socket);
    }
    else {
        perror("Couldn't open socket");
        exit(EXIT_FAILURE);
    }
    close( socketfd );
}

А теперь клиент:

int main(void) {

int sockfd;

struct sockaddr_in serv_addr;
char hello[1024] = "Hello";

serv_addr.sin_family = AF_INET; 
serv_addr.sin_port = htons(PORT);

/// I'm not sure about this !! 
inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);

sockfd = socket(AF_INET, SOCK_STREAM, 0);

if( sockfd == 0 ) {
    perror("Opening socket failed");
    exit(EXIT_FAILURE);
}

if( connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) != -1 ) {
    /// Says it sent 1024, but sever doesn't recieve it, what gives ?
    int test = send( sockfd, hello, sizeof(hello), 0);
    std::cout << test << std::endl;
}
else {
    perror("Error");
    exit(EXIT_FAILURE);
}

Как видите, это похоже на код, найденный по ссылке. Серверный код - это просто функция, есть другие части кода, такие как создание пользовательских файлов, но ни одна из них не используется в сетевой части, поэтому я не хотел публиковать еще 800 строк кода даром. Main () сервера - это только я, создающий объект класса сервера и вызывающий start () на нем.

Я бы хотел улучшить, где смогу, поэтому, если вы заметите что-то, что я могу сделать лучше, скажите, пожалуйста, будь то общий стиль кодирования или что-то еще. Кроме того, это мой первый вопрос здесь, и мой первый язык не английский, пожалуйста, будьте осторожны со мной :)

1 Ответ

0 голосов
/ 26 августа 2018

Это проблема с круглыми скобками.

Эта строка:

if( (new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len  ) < 0) ) {

< имеет более высокий приоритет оценки, чем оператор =.

new_socket присваивается оценка accept() < 0, что является ложным выражением, поэтому new_socket присваивается ноль.

Возможно, это то, что вы имели в виду:

if (new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len ) < 0)

Но этогораздо меньше ошибок:

new_socket = accept( socketfd, (struct sockaddr *)&cl_addr, (socklen_t*)&len  ); 
if (new_socket < 0) {
        perror("Couldn't accept request");
        exit(EXIT_FAILURE);
}
...