C++ connect() в клиентской программе на основе UNIX-сокетов не устанавливает соединение с сервером

Я написал простой сервер сокетов на С++ в CentOS 7.0, используя знаменитый интерфейс сокетов Беркли. Я запускаю его на любом порту, и он ждет соединений.

Затем я запускаю свою простую клиентскую программу, также написанную на C++, и отправляю запрос на 192.168.122.1 (этот IP-адрес находится с помощью выполнения команды ip addr), но он отказывается подключаться. Обеспокоенный брандмауэром, я останавливаю httpd.service (APACHE) и выполняю процедуру на порту 80, но безрезультатно и получаю сообщение об ошибке «Отказано в подключении».

Что я должен делать?

** ОБНОВЛЕНИЕ 001 ** когда я запускаю команду netstat -l, я получаю следующий вывод:

.
.
tcp        0      0 0.0.0.0:9005            0.0.0.0:*               LISTEN
.
.

** КОНЕЦ ОБНОВЛЕНИЯ 001 ** Вот результаты:

Клиент --> Отказ в подключении

Сервер --> [Ожидание...]

Вот коды:

КЛИЕНТ:

#include <iostream>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>



using namespace std;


namespace TCP {
    class Client {

    public :
        static bool Connect(int argc, char *argv[]) {


            int returnStatus = 0;


            char* buffer[256];


            if (3 != argc) {
                // warn that the port MUST be specified.
                fprintf(stderr, "Incorrect parameter for port and server's address. Usage: %d <port>.\n", argv[0]);
                exit(1); // shut down the application
            }


            // streaming socket is the same as server's one.
            // Note: we use TCP Streaming and not UDP's datagram.
            int socketObject = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);



            //
            struct sockaddr_in serverObject;

            short int portNumber = atoi(argv[1]);

            /**
             * We use memset() of cstring header
             * to set all uninitialized values of
             * the struct serverObject to zero.
             */
            memset(&serverObject,
                   0, sizeof(serverObject));

            // now set the values properly
            serverObject.
                    sin_family = AF_INET;


            serverObject.sin_addr.s_addr = inet_addr(argv[2]);

            serverObject.
                    sin_port = htons(portNumber);


            // we need now to connect to the server by porting out
            // out socketObject
            returnStatus = connect(socketObject, (sockaddr *)&serverObject, sizeof(serverObject));

            if (returnStatus == 0) {
                fprintf(stdout, "Connect successfully done.");
            }
            else {
                fprintf(stderr, "Connection failed! Error %s\n", strerror(errno));
                close(socketObject);

                exit(errno);
            }

            // now it's time to read the data from the server by using read()
            // we read it up to the point of our buffer size
            returnStatus = read(socketObject, buffer, sizeof(buffer));


            if (returnStatus == -1) {
                fprintf(stderr, "cannot read the data.");
                close(socketObject);
                exit(1);
            }
            else if( returnStatus > 0)
            {
                cout << buffer << endl;
                close(socketObject);
            }
        }
    };
}// end of namespaCE

СЕРВЕР

#include <iostream>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <cstring>
#include <unistd.h>



using namespace std;

const char DATA_BACK_TO_CLIENT[] = "A simple socket server!";

namespace TCP {
    class Server {

    public :
        static bool Connect(int argc, char *argv[]) {

            int returnStatus = 0;

            if (2 != argc) {
                // warn that the port MUST be specified.
                fprintf(stderr, "Incorrect parameter for port. Usage: %d <port>.\n", argv[0]);
                exit(1); // shut down the application
            }

            int socketObject = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

            struct sockaddr_in serverObject;

            int portNumber = atoi(argv[1]);

            /**
     * We use memset() of cstring header
     * to set all uninitialized values of
     * the struct serverObject to zero.
     */
            memset(&serverObject,
                   0, sizeof(serverObject));

            // now set the values properly
            serverObject.
                    sin_family = AF_INET;
            serverObject.sin_addr.
                    s_addr = htonl(INADDR_ANY);
            serverObject.
                    sin_port = htonl(portNumber);


            returnStatus = bind(socketObject, (struct sockaddr *) &serverObject,
                                sizeof(serverObject));

            if (returnStatus != 0) {
                fprintf(stderr, "Cannot do the binding. Socket closed.");
                close(socketObject);
                exit(1);
            }

            returnStatus = listen(socketObject, 5); // 5 is a typical value for backlog
            // which denotes the number of allowed connections in queue, After linux 2.2,
            // only completed connections are counted in the queue.

            if (returnStatus == -1) {
                fprintf(stderr, "Cannot listen on the socketl.");
                close(socketObject);
                exit(1);
            }

            while (1) {
                cout << "Server has started successfully. Info:" << endl;
                cout << "Port Number Listening to: " <<  portNumber << endl;

                int simpleChildSocket = 0;
                struct sockaddr clientSocket = {0};
                int simpleClient = 0;
                socklen_t clientNameLength = sizeof(clientSocket);


                cout << "Listening Status:" << returnStatus << endl;

                /** blocking-state. accept() is a blocking
                 *  function essentially.
                 * **/
                simpleChildSocket = accept(socketObject, &clientSocket,
                                           &clientNameLength);
                cout << "Accept Connection Status: " << simpleChildSocket << endl;
                if (simpleChildSocket == -1) {
                    fprintf(stderr, "Cannot accept connectios.\n");
                    close(socketObject);
                    exit(1);
                }

                /**
         * Handle the incoming request
         * write received data from the server
         */
                write(simpleChildSocket, DATA_BACK_TO_CLIENT, sizeof(DATA_BACK_TO_CLIENT));

                // closing the child socket
                close(simpleChildSocket);
            }

            close(socketObject);
        }
    };
}// end of namespaCE

person Mostafa Talebi    schedule 24.02.2016    source источник
comment
Номер порта задается с помощью htons(), а не htonl().   -  person user207421    schedule 24.02.2016
comment
Не глядя на свой код, когда вы запускаете сервер, убедитесь, что он работает должным образом, запустив netstat -l, чтобы убедиться, что ваш pid прослушивает ожидаемый вами порт. Затем на локальном поле запустите telnet localhost <yourport>, чтобы проверить, подключается ли это, это исключает проблемы с кодом сервера. Если это так, выполните telnet с удаленного ящика и посмотрите, соединяется ли он. Это исключает проблемы с брандмауэром. После этого единственное, что осталось проверить, это ваш клиентский код.   -  person Salgar    schedule 24.02.2016
comment
Салгар, я проверю ваше предложение и доложу   -  person Mostafa Talebi    schedule 24.02.2016
comment
@Salgar Я обновил вопрос, указав результат netstat. Когда я выполняю его, для порта 9005, который является моим тестовым портом для сервера, я получаю: tcp 0 0 0.0.0.0:9005 0.0.0.0:* LISTEN   -  person Mostafa Talebi    schedule 24.02.2016
comment
Это работает. Спасибо @EJP. Проблема заключалась в том, что htols() нужно было использовать для преобразования целых чисел порта. Вы можете опубликовать это как ответ.   -  person Mostafa Talebi    schedule 24.02.2016


Ответы (1)


Номер порта должен быть установлен с помощью htons(),, а не htonl()..

person user207421    schedule 24.02.2016