• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Многопоточный чат на Winsock

  • Автор темы sergg
  • Дата начала
S

sergg

Всем привет. Мне необходимо написать многопоточный чат. При написании, у меня возникла проблема. Я пишу по примеру из "Самоучитель игры на WinSock2". В книге приведен пример эхо-сервера, т.е. написать на его примере сервер для чата - не должно составить особой проблемы.
Сейчас я нахожусь на стадии написания сервера. Возникла проблема с многопоточностью. В книге все просто: клиент коннектится к серверу а далее вызывается функция CreateThread с одним из параметров SexToClient, где SexToClient - функция, обслуживающая клиента. Вот код данной функции:
C++:
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);
// цикл эхо-сервера: прием строки от клиента и возвращение ее клиенту
while( (int 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;
}
По этой функции у меня возникло несколько вопросов:
1) в строке "my_sock=((SOCKET *) client_socket)[0];" что значит [0]?
2) что значит DWORD WINAPI? Прошу не отправлять меня читать про WinApi. Я представляю что это такое, как и для чего используется. Просто прошу пояснить, что значат эти два слова перед описанием функции.
3) Ну и самый главный вопрос, который у меня возник. Как отправлять сообщение пользователя не ему самому, а всем пользователям сразу?
Я так понимаю, что надо как-то создать массив типа SOCKET, в котором будут хранится все сокеты, по которым подключены клиенты, и в цикле отправлять это сообщение всем, но как это сделать в потоке? Или может есть еще какие-нибудь варианты?

Подскажите, пожалуйста, ответы на эти вопросы.
 
A

Antonim

...
2) что значит DWORD WINAPI? Прошу не отправлять меня читать про WinApi. Я представляю что это такое, как и для чего используется. Просто прошу пояснить, что значат эти два слова перед описанием функции.
Странно что задаешь такой вопрос, зная WinApi))
DWORD - Double Word - возвращаемое значение твоей функцией(32 бита без знака), а WINAPI - определяет принятую последовательность(порядок) передачи параметров в функцию. Больше ничего сказать не могу...
 
W

werasaimon

вот так


C++:
#include <iostream>
#include <windows.h>
#include <winsock2.h>
#include<stdio.h>
#include <string>

using namespace std;






SOCKET massiv_socket[1000];
int num_massiv_socket = 0;





DWORD WINAPI SexToClient(LPVOID client_socket)
{
SOCKET my_sock;
my_sock=((SOCKET*) client_socket)[0];

char buff[20*1024];
int bytes_recv;

int Numer = num_massiv_socket - 1;

while( (bytes_recv = recv(my_sock,&buff[0],sizeof(buff),0)) && bytes_recv !=SOCKET_ERROR)
{





for (int i = 0; i < num_massiv_socket; i ++) {
if (massiv_socket[i] != my_sock)
send(massiv_socket[i], &buff[0] , bytes_recv,0);
}

Sleep(1);
}


num_massiv_socket--;
closesocket(my_sock);
return 0;
}




int main() {


// unsigned long flag = true;

//char buff[256];
WSAData ws;
WSAStartup(0x0202 ,&ws );


SOCKET mysocket;
mysocket = socket(AF_INET , SOCK_STREAM , 0);

sockaddr_in local_addr;
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(666);
local_addr.sin_addr.S_un.S_addr = 0;





//int i = 1;
//setsockopt(mysocket,SOL_SOCKET,SO_REUSEADDR,(char *)&i,sizeof (i));

if(bind(mysocket , (sockaddr*)&local_addr , sizeof(local_addr)))
{
closesocket(mysocket);
WSACleanup();
}


listen(mysocket , 0x100);



SOCKET client_socket;
sockaddr_in client_addr;
int client_addr_size=sizeof(client_addr);



while((client_socket=accept(mysocket, (sockaddr *)
&client_addr, &client_addr_size)))

{

massiv_socket[num_massiv_socket] = client_socket;
num_massiv_socket++;

DWORD thID;
CreateThread(NULL,0,SexToClient,
&client_socket,0,&thID);


// _beginthread(thread_proc , 0 , &client_socket);

}


closesocket(mysocket);
WSACleanup();

return 0;
}
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!