Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: VS c++ sockets (errors), Пример реализации TCP эхо-сервера  (Прочитано 9648 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Zhuravskiy
Интересующийся

ru
Offline Offline

« : 09-01-2012 19:15 » 

начал узучать сокеты в с++ , нашёл пример клиент серверного приложения.
но возникают ошибки ,не могу понять в чём ошибка.
Код: (C++)
// Пример простого TCP-эхо-сервера
#pragma comment ( lib, "ws2_32.lib" )  // добавил сам стротроку. т.к не находил библиотеку без этой строки хоть в консоли и прописывал "ws2_2.lib"
#include <stdio.h>
#include <winsock2.h> // Wincosk2.h должен быть раньше windows!
#include <windows.h>
#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;
int main(int argc, char* argv[])
{
    char buff[1024]; // Буфер для различных нужд
    printf("TCP SERVER DEMO\n");
    // Шаг 1 - Инициализация Библиотеки Сокетов
    // т.к. возвращенная функцией информация не используется
    // ей передается указатель на рабочий буфер, преобразуемый к указателю
    // на структуру WSADATA.
    // Такой прием позволяет сэкономить одну переменную, однако, буфер
    // должен быть не менее полкилобайта размером (структура WSADATA
    // занимает 400 байт)
    if (WSAStartup(0x0202, (WSADATA *)&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 - ожидание подключений
    // размер очереди - 0x100
    if (listen(mysocket, 0x100))
    {
        // Ошибка
        printf("Error listen %d\n", WSAGetLastError());
        closesocket(mysocket);
        WSACleanup();
        return -1;
    }
    printf("Ожидание подключений...\n");
    // Шаг 5 - извлекаем сообщение из очереди
    SOCKET client_socket; // сокет для клиента
    sockaddr_in client_addr; // адрес клиента (заполняется системой)
    // функции accept необходимо передать размер структуры
    int client_addr_size = sizeof(client_addr);
    // цикл извлечения запросов на подключение из очереди
    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 "Hello, Sailor\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)
    send(my_sock, &buff[0], bytes_recv, 0);
    // если мы здесь, то произошел выход из цикла по причине
    // возращения функцией recv ошибки - соединение с клиентом разорвано
    nclients--; // уменьшаем счетчик активных клиентов
    printf("-disconnect\n"); PRINTNUSERS
    // закрываем сокет
    closesocket(my_sock);
    return 0;
}

ошибки :
Ошибка    2    error LNK1120: 1 неразрешенных внешних элементов    c:\users\a...b\documents\visual studio 2010\Projects\STCP\Debug\STCP.exe    1
Ошибка    1    error LNK2019: ссылка на неразрешенный внешний символ _WinMain@16 в функции ___tmainCRTStartup    c:\Users\a..b\documents\visual studio 2010\Projects\STCP\STCP\MSVCRTD.lib(crtexew.obj)
Записан
Finch
Спокойный
Администратор

il
Offline Offline
Пол: Мужской
Пролетал мимо


« Ответ #1 : 09-01-2012 20:31 » 

Ты проект создал как консольное приложение или как оконное?
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Zhuravskiy
Интересующийся

ru
Offline Offline

« Ответ #2 : 10-01-2012 18:23 » 

спасибо , ошибку понял , это консольное приложение. теперь что бы сделать его Win 32 оконным приложением надо все функции поменять на аналоги для Win32? и засунуть в Winmain?
Записан
Вад
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 10-01-2012 20:08 » 

спасибо , ошибку понял , это консольное приложение. теперь что бы сделать его Win 32 оконным приложением надо все функции поменять на аналоги для Win32? и засунуть в Winmain?
Какие функции? printf в стандартный поток вывода работать будет, только это, разумеется, не будет отображаться в окне. Тут уж тебе решать: если хочешь сразу в окне показывать, то вывод сообщений придётся переделывать, а если хочешь в файл сбрасывать, то переделки минимальны (или можно и вовсе перенаправить стандартный поток в файл из командной строки при запуске приложения).
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines