singlepost

С++ & сокеты & Windows << На главную или назад  

С чего можно начать обучение?
Я начал вот с этой книги ib.mexmat.ru/books/24321 но там в примерах есть ошибки. Сейчас пытаюсь сварганить простейшее клиент-серверное приложение с помощью этого примера //forum.codenet.ru/showthread.php?t=18997, но там тоже возникли проблемы при соединении через интернет, а не по локалке.

28 ответов в теме “С++ & сокеты & Windows”

  1. 14
    Денис Слепцов ответил:

    Нет, не заработало :( Подключение происходит – и тут же разрывается. В роутере открывал 6666 и 666 порты для TSP, ни через один постоянное соединение не установилось. Пробую подключиться к серверу telnet-ом – глухо, как в танке. Зло***чий Домолинк :(

  2. 13
    Денис Слепцов ответил:

    всё наладил, дело было в роутере – пробросил нужные порты и заработало :-)

  3. 12
    Нгамдкхе Кверос ответил:

    узнай ещё свой ip например набрав в командной строке ipconfig или в свойствах установившегося соединения ethernet там тоже самое?

  4. 11
    Денис Слепцов ответил:

    // Пример простого TCP-сервера

    #include <stdio.h>
    #include <iostream.h>
    #include <winsock2.h>
    #pragma comment(lib, "WSock32.lib") // Используем эту библиотеку

    #define MY_PORT 666 // Порт, который слушает сервер – 666

    // макрос для печати количества активных пользователей
    #define PRINTNUSERS if (nclients) printf("%d user on-line\n", nclients); \
    else printf("No User on line\n");

    // прототип функции, обслуживающий подключившихся пользователей
    DWORD WINAPI SexToClient(LPVOID client_socket);

    // глобальная переменная – количество активных пользователей
    int nclients = 0;
    void RussianMessage(char *str);
    int main(int argc, char* argv[])
    {
    char buff[1024]; // Буфер для различных нужд

    printf("TCP SERVER DEMO \n");
    // Шаг 1 – Инициализация Библиотеки Сокетов
    // т.к. возвращенная функцией информация не используется
    // ей передается указатель на рабочий буфер, преобразуемый к указателю
    // на структуру WSAD?4??4??1?.
    // Такой прием позволяет сэкономить одну переменную, однако, буфер
    // должен быть не менее полкилобайта размером (структура WSAD?4??4??1?
    // занимает 400 байт)
    if (WSAStartup(0×0202, (WSAD?4??4??1? *)&buff[0]))
    {
    // Ошибка!
    printf("Error WSAStartup %d\n", WSAGetLastError());
    return -1;
    }

    // Шаг 2 – создание сокета
    SOCKET mysocket;
    // AF_INET – сокет Интернета
    // SOCK_STREAM – потоковый сокет (с установкой соединения)
    // 0 – по умолчанию выбирается TCP протокол
    if ((mysocket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
    // Ошибка!
    printf("Error socket %d\n", WSAGetLastError());
    WSACleanup(); // Деиницилизация библиотеки Winsock
    return -1;
    }

    // Шаг 3 – связывание сокета с локальным адресом
    sockaddr_in local_addr;
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(MY_PORT); // не забываем о сетевом порядке!!!
    local_addr.sin_addr.s_addr = 0; // сервер принимает подключения
    // на все свои IP-адреса

    // вызываем bind для связывания
    if (bind(mysocket, (sockaddr *)&local_addr, sizeof(local_addr)))
    {
    // Ошибка
    printf("Error bind %d\n", WSAGetLastError());
    closesocket(mysocket); // закрываем сокет!
    WSACleanup();
    return -1;
    }

    // Шаг 4 – ожидание подключений
    // размер очереди – 0×100
    if (listen(mysocket, 0×100))
    {
    // Ошибка
    printf("Error listen %d\n", WSAGetLastError());
    closesocket(mysocket);
    WSACleanup();
    return -1;
    }

    RussianMessage("Ожидание подключений…");

    // Шаг 5 – извлекаем сообщение из очереди
    SOCKET client_socket; // сокет для клиента
    sockaddr_in client_addr; // адрес клиента (заполняется системой)

    // функции accept необходимо передать размер структуры
    int client_addr_size = sizeof(client_addr);

  5. 10
    Денис Слепцов ответил:

    // цикл извлечения запросов на подключение из очереди
    while ((client_socket = accept(mysocket, (sockaddr *)&client_addr, \
    &client_addr_size)))
    {
    nclients++; // увеличиваем счетчик подключившихся клиентов

    // пытаемся получить имя хоста
    HOSTENT *hst;
    hst = gethostbyaddr((char *)&client_addr. sin_addr.s_addr, 4, AF_INET);

    // вывод сведений о клиенте
    printf("+%s [%s] new connect!\n",
    (hst) ? hst->h_name : "", inet_ntoa(client_addr.sin_addr));
    PRINTNUSERS

    // Вызов нового потока для обслужвания клиента
    // Да, для этого рекомендуется использовать _beginthreadex
    // но, поскольку никаких вызовов функций стандартной Си библиотеки
    // поток не делает, можно обойтись и CreateThread
    DWORD thID;
    CreateThread(NULL, NULL, SexToClient, &client_socket, NULL, &thID);
    }
    return 0;
    }

    // Эта функция создается в отдельном потоке
    // и обсуживает очередного подключившегося клиента независимо от остальных
    DWORD WINAPI SexToClient(LPVOID client_socket)
    {
    SOCKET my_sock;
    my_sock = ((SOCKET *)client_socket)[0];
    char buff[20 * 1024];
    #define sHELLO "Приём!\r\n"

    // отправляем клиенту приветствие
    send(my_sock, sHELLO, sizeof(sHELLO), 0);

    // цикл сервера
    int bytes_recv;
    while ((bytes_recv = recv(my_sock, &buff[0], sizeof(buff), 0)) &&
    bytes_recv != SOCKET_ERROR){
    buff[bytes_recv]=0;
    cout << buff; cout << endl;
    fgets(&buff[0], sizeof(buff) – 1, stdin);
    send(my_sock, &buff[0], bytes_recv, 0);
    }

    // если мы здесь, то произошел выход из цикла по причине
    // возращения функцией recv ошибки – соединение с клиентом разорвано
    nclients–; // уменьшаем счетчик активных клиентов
    printf("-disconnect\n"); PRINTNUSERS

    // закрываем сокет
    closesocket(my_sock);
    return 0;
    }

    void RussianMessage(char *str)
    {
    char message[20 * 1024];
    CharToOem(str,message);
    cout<<message <<endl;
    }

  6. 9
    Денис Слепцов ответил:

    К Интернету подключен через провайдера Домолинк-Воронеж. Свой ip узнавал с помощью 2ip.ru Через прокси не сижу. Хз что делать, в общем.

  7. 8
    Денис Слепцов ответил:

    Собственно, код базируется на статье Криса, ссылкая на которую есть выше

    // Пример простого TCP-клиента
    #include <stdio.h>
    #include <string.h>
    #include <iostream.h>
    #include <winsock2.h>
    #pragma comment(lib, "WSock32.lib") // Используем эту библиотеку

    #define PORT 666
    #define SERVERADDR "77.45.165.105" // 127.0.0.1
    void RussianMessage(char *str);

    int main(int argc, char* argv[])
    {
    char buff[1024];
    printf("TCP DEMO CLIENT\n");

    // Шаг 1 – инициализация библиотеки Winsock
    if (WSAStartup(0×202, (WSAD?4??4??1? *)&buff[0]))
    {
    printf("WSAStart error %d\n", WSAGetLastError());
    return -1;
    }

    // Шаг 2 – создание сокета
    SOCKET my_sock;
    my_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (my_sock < 0)
    {
    printf("Socket() error %d\n", WSAGetLastError());
    return -1;
    }

    // Шаг 3 – установка соединения
    // заполнение структуры sockaddr_in – указание адреса и порта сервера
    sockaddr_in dest_addr;
    dest_addr.sin_family = AF_INET;
    dest_addr.sin_port = htons(PORT);
    HOSTENT *hst;

    // преобразование IP адреса из символьного в сетевой формат
    if (inet_addr(SERVERADDR) != INADDR_NONE)
    dest_addr.sin_addr.s_addr = inet_addr(SERVERADDR);
    else
    {
    // попытка получить IP адрес по доменному имени сервера
    if (hst = gethostbyname(SERVERADDR))
    // hst->h_addr_list содержит не массив адресов,
    // а массив указателей на адреса
    ((unsigned long *)&dest_addr.sin_addr)[0] =
    ((unsigned long **)hst->h_addr_list)[0][0];
    else
    {
    printf("Invalid address %s\n", SERVERADDR);
    closesocket(my_sock);
    WSACleanup();
    return -1;
    }
    }

    // адрес сервера получен – пытаемся установить соединение
    if (connect(my_sock, (sockaddr *)&dest_addr, sizeof(dest_addr)))
    {
    printf("Connect error %d\n", WSAGetLastError());
    return -1;
    }

    RussianMessage("Соединение с ");
    RussianMessage(SERVERADDR);
    RussianMessage(" успешно установлено\n \
    Type quit for quit\n\n");
    cout << endl;

    // Шаг 4 – чтение и передача сообщений
    int nsize;
    while ((nsize = recv(my_sock, &buff[0], sizeof(buff) – 1, 0)) != SOCKET_ERROR)
    {
    // ставим завершающий ноль в конце строки
    buff[nsize] = 0;

    // выводим на экран
    RussianMessage("Юстас=>Алексу:");
    RussianMessage(buff);
    cout << endl;
    // читаем пользовательский ввод с клавиатуры
    RussianMessage("Алекс=>Юстасу:");
    cin >> buff;

    // проверка на "quit"
    if (!strcmp(&buff[0], "quit\n"))
    {
    // Корректный выход
    printf("Exit…");
    closesocket(my_sock);
    WSACleanup();
    return 0;
    }

    // передаем строку клиента серверу
    send(my_sock, &buff[0], strlen(&buff[0]), 0);
    }
    printf("Recv error %d\n", WSAGetLastError());
    closesocket(my_sock);
    WSACleanup();
    return -1;
    }

    void RussianMessage(char *str)
    {
    char message[256];
    CharToOem(str,message);
    cout<<message;
    }

  8. 7
    Нгамдкхе Кверос ответил:

    #5 я тут на кофейной гуще гадаю.. щас… щас.. вижу.. вижу.. ошибка в коде у тебя вот в чём дело.

    чего запускаешь на локальный айпишник, на что сам биндишься? как к интернету подключён?

  9. 6
    Любомир Семків ответил:

    От посмотри, с калбеками, удобно:
    //www.alhem.net/Sockets/

    C++ Stream Compatible TCP/IP Sockets
    //sourceforge.net/projects/cpp-sockets/

    //sourceforge.net/projects/fedlibrary/

    //netclass.sourceforge.net/

  10. 5
    Любомир Семків ответил:

    Поищи любу для ++ какую нибудь.

  11. 4
    Денис Слепцов ответил:

    Что-то не срастается – при запуске с локальным ip (127.0.0.1) всё работает нормально. Как только меняю на интернет-ip – соединение не создаётся. :-(

  12. 3
    Денис Слепцов ответил:

    Спасибо большое,очень понятно написано! :-)

  13. 2
    Vova Mastobaev ответил:

    //www.citforum.ru/book/cook/winsock.shtml
    там разве что про асинхронные сокеты не написано

  14. 1
    Денис Слепцов ответил:

    P.S. С и основы C++ знаю.

Клуб программистов работает уже ой-ой-ой сколько, а если поточнее, то с 2007 года.