Чат
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
|