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

Чат

07.09.2016, 21:41. Показов 2057. Ответов 1
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер, уважаемые форумчане! Пишу сетевой чат . Имеются классы Server и Client. Сервер работает, а вот с клиентом проблема((( По отладчику вижу, что ошибка в методе Connect в этом месте:
if (SOCKET_ERROR == ::connect(Socket,
(struct sockaddr*)&addr_server,
sizeof(addr_server)))
throw std::exception("Ошибка connect = ");

Но не пойму где именно((( просьба помочь кто, чем сможет.
Также, когда ловлю исключения, мне выдает код ошибки, а как вывести перед кодом текст ("Ошибка connect = " и тд)?

Server.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
#pragma once
 
#include <Windows.h>
#include <Winsock.h>
#include <iostream>
using namespace std;
#pragma comment( lib, "Ws2_32.lib" )
 
#define COUNT_CLIENT    5
#define LOGIN           10
#define SIZE_BUF        1024
static CRITICAL_SECTION cs = { 0 };
//DWORD WINAPI Thread(LPVOID);
class Server
{
 
    struct Client
    {
        char login[LOGIN];
        SOCKET Socket;
    };
 
    struct ParamToThread
    {
        int i;
        Server*p;
    };
 
    Client clients[COUNT_CLIENT] = { 0 };
    int count_client = 0;
    friend DWORD WINAPI Thread(LPVOID _param);
    SOCKET Socket;
 
public:
    Server();
    ~Server();
    void Initialize();
    void SocketInit();
    void Bind();
    void Listen();
    void Chat();
    
};
Server.cpp
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include "stdafx.h"
#include "Server.h"
 
 
Server::Server()
{
}
 
Server::~Server()
{
}
void Server::Initialize()
{
 
    WSADATA wsd = { 0 };                       //структура WSADATA
    if (::WSAStartup(0x0202, &wsd)) //инициализация библиотеки Windows Socket и проверка
        throw std::exception("Ошибка WSAStartup");
}
 
void Server::SocketInit()
{
    this->Socket = ::socket(AF_INET, SOCK_STREAM, 0);  //создаем сокет
                           //проверка создания сокета
    if (Socket == SOCKET_ERROR)
    throw std::exception ("Ошибка socket = " );
        
}
void Server::Bind()
{
    sockaddr_in local_addr = { 0 };
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = ::htons(33333);
    local_addr.sin_addr.s_addr = NULL;
 
    //связываем ip-адрес и порт и проверяем
    if (bind(this->Socket, (sockaddr*)&local_addr, sizeof(local_addr)) == SOCKET_ERROR)
        throw std::exception("Ошибка bind = ");
 
    
}
void Server::Listen()
{
    //количество клиентов, которые могут подключиться
    if (::listen(this->Socket, COUNT_CLIENT) == SOCKET_ERROR)
        throw std::exception("Ошибка listen = ");
 
    cout << "Ожидание подключений" << endl;
}
void Server::Chat()
{
    ::InitializeCriticalSection(&::cs);  //инициализируем критическую секцию
                                         //вечный цикл
    while (true)
    {
        //структура информации о клиенте
        SOCKET client_socket = NULL;
        sockaddr_in client_addr = { 0 };
 
        int client_addr_size = sizeof(client_addr);
 
        //принимаем подключившегося клиента
        client_socket = ::accept(this->Socket,
            (sockaddr*)&client_addr,
            &client_addr_size);
        if (INVALID_SOCKET == client_socket)
            throw std::exception("Ошибка accept = "); 
        else
        {  //если количество клиентов меньше возможного 
            if (count_client < COUNT_CLIENT)
            { //входим в критическую секцию
                ::EnterCriticalSection(&::cs);
                //для каждого клиента
                for (int i = 0; i < COUNT_CLIENT; i++)
                {
                    if (!clients[i].Socket) //если сокет клиента равен 0
                    {
                        clients[i].Socket = client_socket; //присваиваем сокету клиента новый сокет
                                                           //создаем поток для каждого клиента
                        ParamToThread ptt = { i, this };
 
                        HANDLE hThread = ::CreateThread(NULL,
                            NULL,
                            Thread,
                            &ptt,
                            NULL,
                            NULL);
                        if (!hThread)
                            cout << "Ошибка CreateThread = " << ::GetLastError();
                        else
                        {
                            count_client++; //переходим к следующему клиенту
                            ::CloseHandle(hThread);//закрываем дескриптор потока
                        }
                        break;
                    }
                }
                ::LeaveCriticalSection(&::cs);//покидаем критическую секцию
            }
        }
 
    }
 
    ::DeleteCriticalSection(&::cs);
    ::closesocket(this->Socket);
 
    ::WSACleanup();
 
    
}
//функция потока
DWORD WINAPI Thread(LPVOID _param)
{
    Server::ParamToThread ptt = *reinterpret_cast<Server::ParamToThread*>(_param);
    
    //запускаем цикл для каждого клиента
    while (ptt.p->clients[ptt.i].Socket != SOCKET_ERROR)
    {
        //буферы
        char buf_recv[SIZE_BUF] = { 0 };
        char buf_send[SIZE_BUF] = { 0 };
        //прием данных
        int size_recv = ::recv(ptt.p->clients[ptt.i].Socket,
            buf_recv,
            sizeof(buf_recv) - 1,
            0);
        if (size_recv != SOCKET_ERROR && size_recv)//???
        {
            //если длина логина клиента равна 0 (новый клиент)
            if (!strlen(ptt.p->clients[ptt.i].login))
            {
                //формируем логин клиента
                strcpy_s(ptt.p->clients[ptt.i].login, sizeof(ptt.p->clients[ptt.i].login) - 1, buf_recv);
                //выводим на консоль информацию о вошедшем клиенте
                sprintf_s(buf_send, sizeof(buf_send) - 1, "В чат вошел: %s", ptt.p->clients[ptt.i].login);
 
            }
            //иначе выводим полученное сообщение от клиента
            else
                sprintf_s(buf_send, sizeof(buf_send) - 1, "%s:%s", ptt.p->clients[ptt.i].login, buf_recv);
            //входим в критическую секцию
            ::EnterCriticalSection(&::cs);
            //для каждого клиента
            for (int i = 0; i < COUNT_CLIENT; i++)
            {
                //рассылаем сообщение другим клиентам
                if (ptt.p->clients[ptt.i].Socket && ptt.p->clients[ptt.i].Socket != SOCKET_ERROR && i != ptt.i)
                {
 
                    int size_send = ::send(ptt.p->clients[ptt.i].Socket,
                        buf_send,
                        strlen(buf_send),
                        0);
                    if (size_send == SOCKET_ERROR)
                    {
                        ::closesocket(ptt.p->clients[ptt.i].Socket);
                        memset(&ptt.p->clients[ptt.i], 0, sizeof(ptt.p->clients[ptt.i]));
                        ptt.p->count_client--;
                    }
 
                }
 
            }
 
            ::LeaveCriticalSection(&::cs);
        }
 
    }
 
    ::EnterCriticalSection(&::cs);
    ::closesocket(ptt.p->clients[ptt.i].Socket);
    memset(&ptt.p->clients[ptt.i], 0, sizeof(ptt.p->clients[ptt.i]));
    ptt.p->count_client--;
    ::LeaveCriticalSection(&::cs);
 
    return 0;
 
}
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
#include "stdafx.h"
#include <Windows.h>
#include <Winsock.h>
#include <iostream>
#include "Server.h"
using namespace std;
 
 
int _tmain(int argc, _TCHAR* argv[])
{
 
    TCHAR strNamePC[MAX_PATH] = { 0 };
    DWORD dwSizeName = MAX_PATH;
    GetComputerName(strNamePC, &dwSizeName);
    strNamePC[dwSizeName] = '\0';
    wcout << strNamePC << endl; //получаем и выводим на консоль имя сервера
    try {
 
 
        setlocale(LC_CTYPE, "Russian");
        Server s;
        s.Initialize();
        s.SocketInit();
        s.Bind();
        s.Listen();
        s.Chat();
    }
    catch (exception &msg) 
    {
        cout << GetLastError << endl;
    };
    return 0;
}
Client.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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#pragma once
 
#include "stdafx.h"
#include <Windows.h>
#include <Winsock.h>
#include <iostream>
#include <vector>
using namespace std;
#pragma comment( lib, "Ws2_32.lib" )
 
#define SIZE_IP     17
#define SIZE_BUF    1024
#define LOGIN       10
 
 
 
class Client
{
    char ip_server[SIZE_IP] = { 0 };
    UINT port = 0;
    char login[LOGIN] = { 0 };
    SOCKET Socket;
    friend DWORD WINAPI Thread(LPVOID _param);
public:
    Client();
    ~Client();
    void Initialize();
    void SocketInit();
    void Connect();
    void Chat();
 
};
 
Client.cpp
#include "stdafx.h"
#include "Client.h"
 
 
Client::Client()
{
}
 
 
Client::~Client()
{
}
//метод инициализации клиента
void Client::Initialize()
{
    cout << "Введите ip сервера: ";
    cin >> ip_server;
 
    
    cout << "Введите порт сервера: ";
    cin >> port;
 
    cout << "Введите логин: ";
    cin >> login;
 
    WSADATA wsd = { 0 };      //структура WSADATA
    if (int iRet = ::WSAStartup(0x0202, &wsd))  //инициализация библиотеки Windows Socket и проверка
        throw std::exception("Ошибка WSAStartup = ");
 
}
void Client::SocketInit()
{
 
    SOCKET Socket = ::socket(AF_INET,//создаем сокет                   
        SOCK_STREAM,
        IPPROTO_IP);
    if (Socket == SOCKET_ERROR)
        throw std::exception("Ошибка socket = "); //проверка создания сокета
}
void Client::Connect()
{
    //преобразоваем ip адрес с человеческого формата в сетевой
    struct sockaddr_in  addr_server = { 0 };
    addr_server.sin_addr.s_addr = inet_addr(ip_server);
    if (INADDR_NONE == addr_server.sin_addr.s_addr)
    {
        // определяем информацию о сервере по имени компьютура
        struct hostent *h = ::gethostbyname(ip_server);
 
        if (!h)
        throw std::exception("Ошибка gethostbyname = "); 
 
        addr_server.sin_addr = *(struct in_addr *) h->h_addr_list[0];
 
    }
 
    addr_server.sin_family = AF_INET;
    addr_server.sin_port = ::htons(port); //преобразовываем номер порта в сетевой формат
 
    if (SOCKET_ERROR == ::connect(Socket,
        (struct sockaddr*)&addr_server,
        sizeof(addr_server)))
        throw std::exception("Ошибка connect = "); 
}
void Client::Chat()
{
    HANDLE hThread = ::CreateThread(NULL,
        NULL,
        Thread,
        (LPVOID)Socket,
        NULL,
        NULL);
    if (!hThread)
        throw std::exception("Ошибка CreateThread = ");
 
 
    char    buf_send[SIZE_BUF] = { 0 };
    int     size_send;
    strcpy_s(buf_send, sizeof(buf_send) - 1, login);
    do
    {
        size_send = ::send(Socket,
            buf_send,
            strlen(buf_send),
            0);
        if (size_send != SOCKET_ERROR && size_send == strlen(buf_send))
        {
            memset(buf_send, 0, sizeof(buf_send));
            cin.getline(buf_send, sizeof(buf_send) - 1);
        }
    } while ((size_send != SOCKET_ERROR) || (strcmp(buf_send, "exit") != 0));
 
    ::closesocket(Socket);
 
    ::WSACleanup();
 
    ::WaitForSingleObject(hThread, INFINITE);
 
    ::CloseHandle(hThread);
 
    cin.get();
 
}
 
DWORD WINAPI Thread(LPVOID _param)
{
 
    SOCKET Socket = (SOCKET)_param;
 
    char buf_recv[SIZE_BUF];
    int size_recv;
    do
    {
 
        vector<unsigned char> vec;
 
        memset(buf_recv, 0, sizeof(buf_recv));
        size_recv = ::recv(Socket,
            buf_recv,
            sizeof(buf_recv) - 1,
            0);
        if (size_recv && size_recv != SOCKET_ERROR)
            cout << buf_recv << endl;
    } while (size_recv && size_recv != SOCKET_ERROR);
 
    return 0;
 
}
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
#include "stdafx.h"
#include <Windows.h>
#include <Winsock.h>
#include <iostream>
#include <vector>
#include "Client.h"
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    try {
 
 
        setlocale(LC_CTYPE, "Russian");
        Client c;
        c.Initialize();
        c.SocketInit();
        c.Connect();
        c.Chat();
    }
    catch (exception &msg)
    {
        cout << GetLastError << endl;
    };
 
 
    return 0;
 
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.09.2016, 21:41
Ответы с готовыми решениями:

Чат-бот на C++
Как сделать оффлайн бота для общения?В данный момент изучаю C++ и решил сделать такого!Также надо сделать так чтобы он мог помогать в...

Сделать чат на сокетах
Как сдeлать чат на winapi клиeнт-сepвep на сoкeтах (фopма)? дайте пример пожалуйста!

Многопоточный чат (Threads) на С++
Всем добрый вечер. Прошу извинения если тему разместил не в том разделе, т.к. я долго на эту тему колебался. Суть вопроса следующая:...

1
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
08.09.2016, 10:55
24-я строка последнего файла - что это?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.09.2016, 10:55
Помогаю со студенческими работами здесь

Чат с возможностью обмена файлами
Доброго времени суток, ув. форумчане. Очень нужны примеры/исходники чата (желательно с возможностью обмена файлами) на C++/WinAPI. Искал...

чат между двумя приложениями
вообщем надо разработать чат работающий между двумя приложениями, у меня в целом это сделать получилось , но у меня обязательно необходимо...

Чат через именованный Pipe
Привет всем. Написал чат который запускается из двух файлов на одном компьютере. Все делал через CreateNamedРipe. Можно ли реализовать...

Чат. Общение по локальной сети
Здравствуйте! Мне нужно написать программу для передачи сообщений по локальной сети. Подскажите, пожалуйста, с чего мне надо начать?...

Чат на основе именованных каналов
Как сделать проверку на сервере, что бы он проверял уникальность имени каждого в пользователя пределах чата?


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Кому нужен AOT?
DevAlt 26.03.2026
Решил сделать простой ланчер Написал заготовку: dotnet new console --aot -o UrlHandler var items = args. Split(":"); var tag = items; var id = items; var executable = args;. . .
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере нетипового документа выдачи шин для спецтехники с табличной частью, разработанного в конфигурации КА2. Номеклатура. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru