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

Тема в разделе "MS Visual C++", создана пользователем sergg, 21 июл 2011.

  1. sergg

    sergg Member

    Регистрация:
    9 май 2010
    Сообщения:
    20
    Симпатии:
    0
    Всем привет. Мне необходимо написать многопоточный чат. При написании, у меня возникла проблема. Я пишу по примеру из "Самоучитель игры на 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, в котором будут хранится все сокеты, по которым подключены клиенты, и в цикле отправлять это сообщение всем, но как это сделать в потоке? Или может есть еще какие-нибудь варианты?

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

    Antonim Member

    Регистрация:
    15 дек 2010
    Сообщения:
    15
    Симпатии:
    0
    Странно что задаешь такой вопрос, зная WinApi))
    DWORD - Double Word - возвращаемое значение твоей функцией(32 бита без знака), а WINAPI - определяет принятую последовательность(порядок) передачи параметров в функцию. Больше ничего сказать не могу...
     
  3. werasaimon

    werasaimon New Member

    Регистрация:
    28 дек 2012
    Сообщения:
    1
    Симпатии:
    0
    вот так


    Код (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;
    }
     
Загрузка...

Поделиться этой страницей