Скачиваний:
6
Добавлен:
03.02.2019
Размер:
16.32 Кб
Скачать
#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