Форум программистов, компьютерный форум, киберфорум
C++: Сети
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.92/12: Рейтинг темы: голосов - 12, средняя оценка - 4.92
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 4

Winsock, _beginthreadex()

05.11.2012, 10:14. Показов 2484. Ответов 18
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток дамы и господа, могли вы помочь мне разобраться где я туплю, хочу написать класс-обертку над сокетами, с++ для меня достаточно новый язык и работа с WinSock2.h очень проблематична для меня(
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
cCoolServerSocket::cCoolServerSocket(void)
{
    this->PORT = 666;
    this->BACKLOG = 100;
}
cCoolServerSocket::~cCoolServerSocket(void)
{
    WSACleanup();
}
int cCoolServerSocket::Init()
{
    this->state = "Init...";
    if (WSAStartup(0x0202,(WSADATA *) &buff[0])) 
    {
      // Ошибка!
         this->state = "Error";
         this->errNum = WSAGetLastError();
         return -1;
    }else printf("WSA Inited...\r\n");
    if ((this->serverSocket=socket(AF_INET,SOCK_STREAM,0))<0)
    {
        this->state = "Error";
        this->errNum = WSAGetLastError();
        WSACleanup();// Деиницилизация библиотеки Winsock
        return -1;
    }else printf("Socket Created...\r\n");
    this->local_addr.sin_family = AF_INET;
    this->local_addr.sin_port=htons(this->PORT);// не забываем о сетевом порядке!!!
    this->local_addr.sin_addr.s_addr=INADDR_ANY;
    if (bind(this->serverSocket,(sockaddr *) &this->local_addr, sizeof(this->local_addr)))
    {
        this->state = "Error";
        this->errNum = WSAGetLastError();
        closesocket(this->serverSocket);  // закрываем сокет!
        WSACleanup();
        return -1;
    }else printf("Server Socket binded...\r\n");
    if (listen(this->serverSocket, BACKLOG))
    {
      // Ошибка
        this->state = "Error";
        this->errNum = WSAGetLastError();
        closesocket(this->serverSocket);
        WSACleanup();
        return -1;
    }else printf("Socket Listen...\r\n");
    SOCKET client_socket;       //!!!!!!!!!!!Клиентский сокет
    sockaddr_in client_addr;    //Адрес подключающегося клиента
    int client_addr_size;       //Accept функции необходимо передавать размерность sockaddr_in структуры
    while((client_socket=accept(this->serverSocket, (sockaddr *)&client_addr, &client_addr_size)))
    {
      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
      unsigned int thID;
      _beginthreadex(NULL,NULL,SexToClient,&client_socket,NULL,&thID);
    }
    return 0;
}
unsigned int cCoolServerSocket::SexToClient(LPVOID param)
{
    SOCKET my_sock;
    my_sock=((SOCKET *) param)[0];
    char buff[1024];
    #define sHELLO "Hello, Sailor\r\n"
 
    // отправляем клиенту приветствие 
    send(my_sock,sHELLO,sizeof(sHELLO),0);
 
    // цикл эхо-сервера: прием строки от клиента и
    // возвращение ее клиенту
    int bytes_recv = 0;
    while( (bytes_recv=recv(my_sock,&buff[0],sizeof(buff),0))&& bytes_recv !=SOCKET_ERROR)
      send(my_sock,&buff[0],bytes_recv,0);
    // если мы здесь, то произошел выход из цикла по
    // причине возращения функцией recv ошибки –
    // соединение клиентом разорвано
    // закрываем сокет
    closesocket(my_sock);
    _endthreadex(0);
    return 0;
}
Собственно проблема заключается в том, что в консоли при создании объекта этого класса и выполнении метода Init(), срабатывает client_socket=accept(this->serverSocket, (sockaddr *)&client_addr, &client_addr_size)...
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.11.2012, 10:14
Ответы с готовыми решениями:

C++ WinSock
Здравствуйте. Есть необходимость написать виртуальный файловый сервер, который будет обрабатывать команды пользователей (вроде cd, mk и...

WinSock
Имеется два приложения. Они связываются через winsock... но если отослать что-либо от одного приложения к другому принимающая сторона...

WinSock на C++
Только начинаю осваивать WinSock написал простейшее приложение-сервер и приложение-клиент и че та у меня не работает вот код...

18
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
05.11.2012, 13:26
а что, не должен? может он ошибку возвращает - вы ведь результат не проверяете
1
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 4
05.11.2012, 13:58  [ТС]
Цитата Сообщение от vxg Посмотреть сообщение
а что, не должен? может он ошибку возвращает - вы ведь результат не проверяете
Щас пробну посмотреть что там WSAGetLastError() возвратит...

Судя по всему не должен... По сути accept в данном коде должен тормознуть основной поток для получения запроса на подключение от клиентского сокета (connect(/*аргументы*/)) и когда этот запрос будет получен при успешном выполнении
C++
1
2
while((client_socket=accept(this->serverSocket, (sockaddr *)&client_addr, &client_addr_size)))
{/*Какой-то код*/}
должно выполнится тело цикла, в котором порождается поток.
У меня почему-то
C++
1
2
while((client_socket=accept(this->serverSocket, (sockaddr *)&client_addr, &client_addr_size)))
{/*Какой-то код*/}
выполняется в независимости от того получен запрос на подключение или нет...

Добавлено через 17 минут
Проблема решилась очень просто, я передавал указатель на не инициализированную переменную указывающую на размер структуры client_addr, в следствии чего accept исполнялся с ошибкой и возвращая true. Решение инициализация переменной int client_addr_size:
C++
1
int client_addr_size = sizeof(client_addr);
Вопрос может в целом и не по сетям, но все же: на сколько удачной будет идея хранить в векторе хэндлы потоков, сокеты, и прочие сведения о подключеных клиентах?
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
05.11.2012, 16:02
почему бы и нет. главное что бы этот вектор был защищен критической секцией или иным методом. а вообще читал, что выделение для каждого клиента своего потока - спорная идея ибо тащит за собой большие затраты на переключение потоков при большом количестве клиентов. кто-то излагал информацию, что производительные серверы однопоточные (не выяснял, но чую что наверное так и есть). у меня это превратилось вот в такое (см. вложение).
Вложения
Тип файла: rar socket_engine.rar (6.3 Кб, 35 просмотров)
1
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
05.11.2012, 16:18
...а в итоге вот в такой web-сервер...
Вложения
Тип файла: rar web_server.rar (80.6 Кб, 35 просмотров)
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
08.11.2012, 07:21
Цитата Сообщение от vxg Посмотреть сообщение
что выделение для каждого клиента своего потока - спорная идея ибо тащит за собой большие затраты на переключение потоков при большом количестве клиентов.
А какое тут переключение ?
Создали, поговорили с клиентом и умерли... при чем умерли в месте с инфой клиента...

Может имеется ввиду пул потоков ?
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
08.11.2012, 09:48
Цитата Сообщение от Avazart Посмотреть сообщение
Создали, поговорили с клиентом и умерли
Не. Создали и говорим, говорим, говорим (в конце конечно умрем, но нас интересует процесс обслуживания, т. е. время когда поток жив). Причем для каждого клиента свой поток. И вот процессор все эти потоки обслуживает: то из одного пару инструкций выполнит, то из другого и так по кругу. И каждое переключение сопровождается накладными расходами в виде сохранения регистров и еще чего-то там. Если потоков много, то на одни только переключения процессор будет тратить достаточно много времени.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
08.11.2012, 18:28
Да а если процессоров несколько ?

сли потоков много, то на одни только переключения процессор будет тратить достаточно много времени.
Хех так все зависит от вида нагрузки на сервер...
Что если сессия будет длится долго то что все остальные клиенты будут ждать все это время?
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
09.11.2012, 10:00
Цитата Сообщение от Avazart Посмотреть сообщение
если процессоров несколько
это хорошо. хотя я к своему стыду не знаю потребуются ли от разработчика усилия для того что бы поток попал в другой процесс или это совершается само на уровне ОС.
Цитата Сообщение от Avazart Посмотреть сообщение
если сессия будет длится долго
пусть длиться. однопоточный сервер для каждого подключенного клиента проверяет наличие данных, если они есть принимает их, анализирует достигнут ли конец передачи, если да то формирует и ставит на отправку ответ. единственный момент где остальные будут ждать - это формирование ответа, но от этого никуда не денешься - данные в любом случае надо обрабатывать хоть в однопоточной системе хоть в многопоточной. конечно если процессоров несколько и потоки соседних клиентов выполняются на них будет прирост производительности. но только в том случае если не происходит доступа к разделяемым процессорами объектам или аппаратному обеспечению. есть конечно еще вопрос надежности - если при формировании ответа будет отказ, то выпадение одного потока в осадок не уничтожит другие, однако такого не должно быть в принципе ибо такие "зомби"-потоки рано или поздно завалят сервер. в любом случае процессоров меньше чем предполагаемое среднее количество подключенных клиентов поэтому на каждом процессоре будет сидеть несколько потоков со всеми своими издержками.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
09.11.2012, 18:42
Ниче не понял, о чем вы?

При одном потоке серв просто подвиснит в ожидании клиента, ответа от которого может быть длительное время - а это тупо простой по тому как в это время ничего не обрабатывается, ведь сокет то блокирующий.

Если вы говорите Unix то там не потоки, а процессы - вообщем ветвления... но это принцип тот же ( за исключкнием того что немного растратно "порождать" зато безопастно в плане разделенных данных)
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
09.11.2012, 22:53
Цитата Сообщение от Avazart Посмотреть сообщение
серв просто подвиснит в ожидании клиента
никто не зависнет. даже если сокет блокирующий - надо лишь проверять перед вызовами наличие входящего соединения или входящих данных через select. а когда сокет неблокирующий (как в приведенном в качестве примера движке), то вообще даже тени проблем нет - все обрабатывается без запинок.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
09.11.2012, 23:36
accept() вызывает ожидание
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
10.11.2012, 22:48
Цитата Сообщение от Avazart Посмотреть сообщение
accept() вызывает ожидание
повторюсь
1 для блокирующих надо проверять перед вызовами наличие входящего соединения и висения не будет
2 работаем с неблокирующими
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
13.11.2012, 01:36
Ну допустим сервер почты POP3 (к примеру ), допустим пользователь ввел команду - USER и ввел свой логин, а вот пароль, он подзабыл и тупит-вспоминает его - как бы соединение есть, а обработки нет, так нет следующей команды.

Чем тут поможет select ?
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,461
13.11.2012, 09:10
на сервер почты пересылаются строки с теми или иными командами. пользователь ввел логин - логин отправился, сервер увидел наличие входящих данных, сервер разобрал логин. пользователь думает о пароле - пусть думает, данные не отправляются, сервер не видит наличия входящих данных, сервер крутит цикл без какой-либо остановки. при этом клиенты подключенные через другие сокеты могут спокойно обмениваться с сервером данными.
0
0 / 0 / 0
Регистрация: 05.11.2012
Сообщений: 4
17.11.2012, 13:08  [ТС]
Вопщем использование vector не очень рационально, там свои затраты проц времени на различные итеративные функции + резервирование памяти + освобождение = проще использовать массив указателей ака быстрей он будет выглядеть да + ко в всему 65535+ подключений просто не возможно ибо Backlog ограничивает, можно конечно реализовать эту вещь по кластерному типу, оставлять одно место свободным для направления подключающегося клиента на "соседний" серверный сокет, но я пока только начал учить плюсы Поэтому Мало что смогу
vxd->Спасибо за сорцы!
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
17.11.2012, 19:18
Цитата Сообщение от kima Посмотреть сообщение
Вопщем использование vector не очень рационально, там свои затраты проц времени на различные итеративные функции + резервирование памяти + освобождение = проще использовать массив указателей ака быстрей он будет выглядеть да + ко в всему 65535+ подключений просто не возможно ибо Backlog ограничивает, можно конечно реализовать эту вещь по кластерному типу, оставлять одно место свободным для направления подключающегося клиента на "соседний" серверный сокет, но я пока только начал учить плюсы Поэтому Мало что смогу
Ну так как раз резервирование экономит ресурсы...итеративные затраты думаю весьма малы...
А освобождение памяти не понял как относится к сему.

Основные затраты тут на перераспределение памяти при "быстром расширении" размера

Учитывая что размер структуры данных мал, то затраты будут малы, по крайней мере оправданы.
На крайний случай можно хранить не структуры, а указатели на нее.
0
1259 / 650 / 44
Регистрация: 06.02.2011
Сообщений: 1,654
17.11.2012, 22:04
Цитата Сообщение от kima Посмотреть сообщение
да + ко в всему 65535+ подключений просто не возможно ибо Backlog ограничивает
Что за бред?
0
4 / 4 / 0
Регистрация: 23.09.2012
Сообщений: 83
13.12.2012, 18:47
Разделяемая память нужна по-моему только для меж процессорного общения, а именно цельный кусок памяти нужного объема, что тоже проблематично, хотя это может только в real time
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
13.12.2012, 18:47
Помогаю со студенческими работами здесь

c++ winSock
Всем привет. У меня возникла проблема, не понятно из-за чего не хочет биндить ни клиент, ни сервер. Клиент: //Client-UDP ...

Winsock
Всем привет.Начал разбиратся с сокетами и сразуже появились проблемы отправки и получения данных.Клиент к серверной части конектится...

WinSock
Есть самоучители на чистом Си по теме WinSock??

WinSock
#include &quot;winsock2.h&quot; #define MAX_PACKET_SIZE 4096 WSADATA ws; hostent* hn; char buff ; if (FAILED (WSAStartup (MAKEWORD( 2,...

winsock
Когда в клиенте отправляю сообщение приходит всегда число 10, найдите ошибку пожалуйста! сервер: TForm1 *Form1; TLabel *lb1; SOCKET...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Новые блоги и статьи
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
Программный отбор значений справочника
Maks 21.03.2026
Установка программного отбора значений справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит предопределенное значение перечислений. Процедура. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru