Добавил:
axel17
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Debug UNO Client Server WinAPI / Server Class / Server
.cpp#pragma comment (lib,"ws2_32.lib")
#pragma warning(disable: 4098)
#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS // откл устаревшие предупреждения
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <tchar.h> //в этом файле содержатся определения некоторых полезных макросов
#include <iostream>
#include <windows.h>
#include <ctime>
#include <cstdlib>
#include <deque>
#include "Card.h"
using namespace std;
#define ID_LIST 1
#define ID_BTNCONNECT 2
#define ID_BTNPLAY 3
#define WSA_ACCEPT (WM_USER + 1)
#define WSA_NETEVENT (WM_USER + 2)
char city[128];
int clientCount = 0;
const int MAX_CLIENT = 64;
int currClient = 0;
deque<Card> deck;
struct CardObj {
int x;
int y;
int width;
int height;
};
deque<CardObj> imgCards;
CardObj currentCard;
float wCard = 57.14;
float hCard = 85.75;
char Ccolor[100];
char Cname[100];
char nameCardClient[128];
char colorCardClient[128];
int countCardClient;
char deckFront[128];
SOCKET socketWinner;
char nameWinner[128];
int scoreWinner = 0;
int countWin = 0;
HWND hWnd, lstBox, editIp, editPort, editStaticIp, editStaticPort, btnConnect, textArea, btnPlay;
HDC hdc;
HINSTANCE hInst;
SOCKET serverSocket, clientSocket;
SOCKET Connections[MAX_CLIENT];
SOCKADDR_IN client_addr;
char IP[80];
USHORT PORT;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void OnWSAAccept(HWND, UINT, WPARAM, LPARAM);
void OnWSANetEvent(HWND, UINT, WPARAM, LPARAM);
void createServer(HWND);
int nextClient();
int prevClient();
void sendQueue();
bool isNextClient = true;
bool isSkip = false;
int CALLBACK WinMain(HINSTANCE hInst, HINSTANCE prevInst, LPSTR lmCmdLine, int nCmdShow) {
MSG msg;
WNDCLASS wc;
// Определение класса окна
wc.hInstance = hInst; // Дескриптор текущего приложения
wc.lpszClassName = _T("MainFrame"); // Имя класса окна
wc.lpfnWndProc = WndProc; // Функция окна
wc.style = CS_HREDRAW | CS_VREDRAW; // Стиль окна автоматическая перерисовка окна при изменении его размеров
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Стандартная иконка загрузка иконки если NULL то системная
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Стандартный курсор загрузка стандартного
wc.lpszMenuName = NULL; // Нет меню ссылка на строку главного меню
wc.cbClsExtra = 0; // Нет дополнительных данных класса число доп байт вслед за структурой класса
wc.cbWndExtra = 0; // Нет дополнительных данных окна за экземпляром окна
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 0); // Заполнение окна серым цветом дескриптор кисти преобразование в HBRUSH
// Создание окна
if (!RegisterClass(&wc)) return 0; // Регистрация класса окна
hWnd = CreateWindow(_T("MainFrame"), // Имя класса окна создание окна
_T("Chat Server"), // Заголовок окна
WS_OVERLAPPEDWINDOW, // Стиль окна
50, // x левый верхний угол
50, // y Размеры окна
300, // Width ширина и высота в пикселях
350, // Height
hWnd, // Дескриптор родительского окна
NULL, // Нет меню указатель на структуру меню
hInst, // Дескриптор приложения
NULL); // Дополнительной информации нет
editIp = CreateWindow(_T("EDIT"), _T("127.0.0.1"), WS_VISIBLE | WS_CHILD,
10, 10, 120, 20, hWnd, NULL, hInst, NULL);
editPort = CreateWindow(_T("EDIT"), _T("8080"), WS_VISIBLE | WS_CHILD,
10, 35, 120, 20, hWnd, NULL, hInst, NULL);
btnConnect = CreateWindow(_T("BUTTON"), _T("Start server"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
140, 20, 100, 30, hWnd, (HMENU)ID_BTNCONNECT, hInst, NULL);
btnPlay = CreateWindow(_T("BUTTON"), _T("Play"), WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,
10, 70, 120, 30, hWnd, (HMENU)ID_BTNPLAY, hInst, NULL);
lstBox = CreateWindow(_T("listbox"), NULL, WS_CHILD | WS_VISIBLE | LBS_STANDARD | LBS_WANTKEYBOARDINPUT,
10, 110, 260, 100, hWnd, (HMENU)ID_LIST, hInst, NULL);
ShowWindow(hWnd, nCmdShow);
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);// Функция трансляции кодов нажатой клавиши, транслирует код в клавиатурные сообщения
DispatchMessage(&msg); // Посылает сообщение функции WndProc() возврат обработанного сообщения операционной системе
}
return 0;
}
void printCard() {
char str[128];
wsprintf(str,"Deck: %d\n%s\n%s",
deck.size(),
color[deck.front().getColor()],
name[deck.front().getName()]
);
MessageBox(hWnd,str,"Card",MB_OK);
}
CardObj getNewCard(int x, int y,int width, int height) {
CardObj newCard;
newCard.x = x;
newCard.y = y;
newCard.width = width;
newCard.height = height;
return newCard;
}
void initDeck() {
int p = 0;
float x = 0;
float y = 0;
float width = wCard;
float height = hCard;
char currColor[100];
char currName[100];
while (p < 2)
{
for (colors i = red; i <= blue;i = static_cast<colors>(i+1))
{
if (p < 1)
{
x = 0;
deck.push_back(*new Card(i, zero));
imgCards.push_back(getNewCard(x,y,width,height) );
x += wCard;
}
for (names j = one; j <= takeTwo; j = static_cast<names>(j+1))
{
deck.push_back(*new Card(i, j));
imgCards.push_back(getNewCard(x,y,width,height) );
x += wCard;
}
y += hCard;
x = wCard;
}
p++;
deck.push_back(*new Card(black, wild));
imgCards.push_back( getNewCard(wCard*13,hCard*2,wCard,hCard) );
deck.push_back(*new Card(black, wild));
imgCards.push_back( getNewCard(wCard*13,hCard*3,wCard,hCard) );
deck.push_back(*new Card(black, wildFour));
imgCards.push_back( getNewCard(wCard*13,hCard*4,wCard,hCard) );
deck.push_back(*new Card(black, wildFour));
imgCards.push_back( getNewCard(wCard*13,hCard*5,wCard,hCard) );
}
}
void cardDistr() {
char charCard[128];
for (int j = 0; j < clientCount; j++)
{
for (int i = 0; i < 7 ;i++)
{
wsprintf(charCard, "%s;%s|%d|%d|%d|%d:%d",
name[ deck.front().getName() ] ,
color[ deck.front().getColor() ],
imgCards.front().x,
imgCards.front().y,
imgCards.front().width,
imgCards.front().height,
0
);// 0 - раздача карт
send(Connections[j], charCard, sizeof(charCard), 0);
deck.pop_front();
imgCards.pop_front();
}
}
}
void showFrontCard() {
currentCard.x = imgCards.front().x;
currentCard.y = imgCards.front().y;
currentCard.width = imgCards.front().width;
currentCard.height = imgCards.front().height;
wsprintf(deckFront,"%s;%s|%d|%d|%d|%d:%d",
name[ deck.front().getName() ] ,
color[ deck.front().getColor() ],
imgCards.front().x,
imgCards.front().y,
imgCards.front().width,
imgCards.front().height,
3
);// 1 - означает что эта карта перевернута и видна всем пользователся
for (int ii = 0; ii < clientCount; ii++)
{
send(Connections[ii], deckFront, sizeof(deckFront), 0);
}
deck.pop_front();
imgCards.pop_front();
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg)
{
case WM_CREATE:
{
hdc = GetDC(hWnd);
break;
}
case WSA_ACCEPT: {
OnWSAAccept(hWnd, msg, wParam, lParam);
break;
}
case WSA_NETEVENT: {
OnWSANetEvent(hWnd, msg, wParam, lParam);
break;
}
case WM_COMMAND:
{
switch (LOWORD (wParam)) {
case ID_BTNPLAY: {
initDeck();
cardDistr();
showFrontCard();
sendQueue();
break;
}
/*case ID_LIST: {
if (HIWORD(wParam) == LBN_DBLCLK) {
char lstValue[100];
int number = SendMessage(lstBox, LB_GETCURSEL, 0, 0L);
SendMessage(lstBox, LB_GETTEXT, (WPARAM)number, (LPARAM)lstValue);
}
break;
}*/
case ID_BTNCONNECT: {
char port[10];
GetWindowText(editPort, port, 255);
GetWindowText(editIp, IP, 255);
PORT = atoi(port);
createServer(hWnd);
break;
}
}
break;
}
case WM_DESTROY: {
PostQuitMessage(0);
break;
}
default: { return DefWindowProc(hWnd, msg, wParam, lParam); }
}
return 0;
}
void OnWSAAccept(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
int rc;
// При ошибке отменяем поступление извещений
// в главное окно приложения
if (WSAGETSELECTERROR(lParam) != 0)
{
MessageBox(NULL, "accept Error", "Error", MB_OK);
WSAAsyncSelect (serverSocket, hWnd, 0, 0);
return;
}
// Определяем размер адреса сокета
int clientAddrSize = sizeof(client_addr);
// Разрешаем установку соединения
Connections[clientCount] = accept (serverSocket, (LPSOCKADDR)&client_addr, (int FAR *)&clientAddrSize);
SendMessage(lstBox, WM_SETREDRAW, FALSE, 0L);
char qwe[128];
wsprintf(qwe,"Client %d", clientCount + 1);
SendMessage(lstBox, LB_ADDSTRING, 0, (LPARAM)qwe);
SendMessage(lstBox, WM_SETREDRAW, TRUE, 0L);
//InvalidateRect(lstBox, NULL, TRUE);
int lstLength = SendMessage(lstBox, LB_GETCOUNT, 0, 0L);
if (Connections[clientCount] == INVALID_SOCKET)
{
MessageBox(NULL, "accept Error, invalid socket ", "Error", MB_OK);
return;
}
// Если на данном сокете начнется передача данных от
// клиента, в главное окно приложения поступит
// сообщение WSA_NETEVENT.
// Это же сообщение поступит при разрыве соединения
rc = WSAAsyncSelect (Connections[clientCount], hWnd, WSA_NETEVENT, FD_READ | FD_CLOSE);
if (rc > 0)
{
closesocket (Connections[clientCount]);
MessageBox(NULL, "WSAAsyncSelect Error", "Error", MB_OK);
return;
}
clientCount++;
}
void sendQueue() {
char waitMsg[128];
for (int i = 0;i < clientCount;i++)
{
if (Connections[i] != Connections[currClient])
{
wsprintf(waitMsg," ; |%d| | | :%d",0,1);
send(Connections[i], waitMsg, sizeof(waitMsg), 0);
} else
{
wsprintf(waitMsg," ; |%d| | | :%d",1,1);
send(Connections[i], waitMsg, sizeof(waitMsg), 0);
}
}
}
int nextClient() {
if (currClient == clientCount-1) {
currClient = 0;
}
else {
currClient++;
}
return 0;
}
int prevClient() {
if (currClient == 0) {
currClient = clientCount - 1;
}
else {
currClient--;
}
return 0;
}
void validCard(SOCKET socket) {
}
void OnWSANetEvent(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
char res[128];
char msgCity[128];
char *token;
int x;
int y;
int width;
int height;
char charFlag[128];
int rc;
if (WSAGETSELECTEVENT(lParam) == FD_READ)// RRRRRRRRRRRRRRRRREEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAADDDDDDDDDDDDDDD
{
rc = recv ((SOCKET)wParam, res, sizeof(res), 0);
if (rc > 0)
{
//if ((SOCKET)wParam != Connections[currClient]) {
// wsprintf(msgCity, "Ждите очередь; | | | | :%d",4); // Ждать очередь
// send((SOCKET)wParam, msgCity, sizeof(msgCity), 0);
//}else {
token = strtok(res, ";");
wsprintf(nameCardClient,"%s", token);
token = strtok(NULL, ";");
wsprintf(colorCardClient,"%s", token);
token = strtok(colorCardClient, "|");
token = strtok(NULL, "|");
wsprintf(charFlag,"%s",token);
x = atoi(charFlag);
token = strtok(NULL, "|");
wsprintf(charFlag,"%s",token);
y = atoi(charFlag);
token = strtok(NULL, "|");
wsprintf(charFlag,"%s",token);
width = atoi(charFlag);
token = strtok(NULL, "|");
wsprintf(charFlag,"%s",token);
height = atoi(charFlag);
token = strtok(charFlag,":");
token = strtok(NULL,":");
wsprintf(charFlag,"%s",token);
int flag = atoi(charFlag);
if (flag == 1)// 1 - клиент берет карту
{
char charCard[128];
wsprintf(charCard, "%s;%s|%d|%d|%d|%d:%d",
name[ deck.front().getName() ],
color[ deck.front().getColor() ],
imgCards.front().x,
imgCards.front().y,
imgCards.front().width,
imgCards.front().height,
0
);
send((SOCKET)wParam, charCard, sizeof(charCard), 0);
deck.pop_front();
imgCards.pop_front();
} else if (flag == 2) // клиент походил
{
char qwe[128];
wsprintf(qwe, "%s;%s|%d|%d|%d|%d:%d",
nameCardClient,
colorCardClient,
x,
y,
width,
height,
3
);
for (int i = 0;i<clientCount;i++)
{
if ((SOCKET)wParam != Connections[i])
{
send(Connections[i], qwe, sizeof(qwe), 0);
}
}
if (isNextClient)
{
nextClient();
} else
{
prevClient();
}
sendQueue();
//char testCurrCl[128];
//wsprintf(testCurrCl,"clientCount: %d\ncurrClient: %d",clientCount, currClient);
//MessageBox(NULL,testCurrCl,"testCurrClient",MB_ICONINFORMATION);
}else if(flag == 3) // подсчет очков победителя
{
wsprintf(nameWinner,"%s",nameCardClient);
socketWinner = ( SOCKET )wParam;
char winMsg[128];
wsprintf(winMsg," ; | | | | :%d",5);
for (int i = 0; i < clientCount; i++)
{
if ( (SOCKET)wParam != Connections[i] )
{
send(Connections[i],winMsg,sizeof(winMsg),0);
}
}
} else if (flag == 5) // skip
{
if (isNextClient)
{
nextClient();
} else
{
prevClient();
}
}else if (flag == 6)// moveback
{
isNextClient ? isNextClient = false : isNextClient = true;
if (isNextClient)
{
nextClient();
} else
{
prevClient();
}
sendQueue();
}else if(flag == 7){
char scoreChar[128];
wsprintf(scoreChar, "%d", x);
scoreWinner += atoi(scoreChar);
countWin++;
if (countWin == clientCount - 1)
{
char winner[128];
wsprintf(winner,"%s; |%d | | | :%d",nameWinner,scoreWinner,6); // говорим всем что выйграк какой-то игрок
for (int i = 0; i < clientCount; i++)
{
if (Connections[i] != socketWinner)
{
send(Connections[i],winner,sizeof(winner),0);
} else
{
char winnMsg[128];
wsprintf(winnMsg, " ; |%d | | | :%d", scoreWinner, 7); // Поздравляем победтеля
send(Connections[i],winnMsg,sizeof(winnMsg),0);
}
}
}
} else if (flag == 8)
{
deck.clear();
imgCards.clear();
char deckSize[128];
wsprintf(deckSize,"%d",deck.size());
}
}
return;
}
// Если соединение завершено, выводми об этом сообщение
else if (WSAGETSELECTEVENT(lParam) == FD_CLOSE)
{
MessageBox(hWnd, "Client disconnected", "Server", MB_OK);
clientCount--;
SendMessage(lstBox, LB_DELETESTRING, clientCount, (LPARAM)lParam);
}
}
void createServer(HWND hWnd) {
WSADATA wsData;
WORD version = MAKEWORD(2, 2);
if (WSAStartup(version, &wsData))
{
MessageBox(hWnd, _T("WSAStartup Error"), _T("Error"), MB_OK | MB_ICONHAND);
return;
}
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET) // AF_INET - сокет Интернета
{ // SOCK_STREAM - потоковый сокет (с установкой соединения)
MessageBox(hWnd, _T("Error socket"), _T("Error"), MB_OK | MB_ICONHAND);
// Деиницилизация библиотеки Winsock
WSACleanup();
return;
}
// Шаг 3 связывание сокета с локальным адресом
sockaddr_in local_addr;
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(int(PORT));
local_addr.sin_addr.s_addr = inet_addr(IP); //если 0 то сервер принимает подключения на все IP-адреса
// вызываем bind для связывания
if (bind(serverSocket, (sockaddr *)&local_addr, sizeof(local_addr)))
{
MessageBox(hWnd, _T("Error socket"), _T("Error"), MB_OK | MB_ICONHAND);
closesocket(serverSocket); // закрываем сокет!
WSACleanup();
return;
}
// Шаг 4 ожидание подключений размер очереди – 0x100
if (listen(serverSocket, 1) == SOCKET_ERROR)
{
MessageBox(hWnd, _T("Error listen"), _T("Error"), MB_OK | MB_ICONHAND);
closesocket(serverSocket);
WSACleanup();
return;
}
// При попытке установки соединения главное окно приложения
// получит сообщение WSA_ACCEPT
int rc;
rc = WSAAsyncSelect (serverSocket, hWnd, WSA_ACCEPT, FD_ACCEPT);
if (rc > 0)
{
closesocket (serverSocket);
MessageBox(NULL, "WSAAsyncSelect Error", "Error", MB_OK);
return;
}
//MessageBox(hWnd, "Server started", "Server", MB_OK);
}
Соседние файлы в папке Server Class