Главная » Рефераты    
рефераты Разделы рефераты
рефераты
рефератыГлавная
рефератыЕстествознание
рефератыУголовное право уголовный процесс
рефератыТрудовое право
рефератыЖурналистика
рефератыХимия
рефератыГеография
рефератыИностранные языки
рефератыРазное
рефератыИностранные языки
рефератыКибернетика
рефератыКоммуникации и связь
рефератыОккультизм и уфология
рефератыПолиграфия
рефератыРиторика
рефератыТеплотехника
рефератыТехнология
рефератыТовароведение
рефератыАрхитектура
рефератыАстрология
рефератыАстрономия
рефератыЭргономика
рефератыКультурология
рефератыЛитература языковедение
рефератыМаркетинг товароведение реклама
рефератыКраеведение и этнография
рефератыКулинария и продукты питания
рефераты
рефераты Информация рефераты
рефераты
рефераты

Курсовая: Сетевые крестики нолики

Курсовая: Сетевые крестики нолики

Курсовая: Сетевые крестики нолики

ЧЕЛЯБИНСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

ОТЧЕТ

о практической работе по дисциплине «Сети ЭВМ»

Факультет: математический Выполнила: Насибулина

Раиса Сулеймановна

Специальность: прикладная Группа: МП-402

математика

Кафедра: системного Проверил: Соколов

Андрей Анатольевич

программирования

Челябинск 2004

Содержание

1. Задание. 3

2. Используемые сетевые сообщения. 4

3. Основные функции программы. 5

4. Процессы. 7

Диаграммы: 8

5. Текст программы. 100

1. Задание.

Разработать приложения клиент и сервер для сетевой игры «Крестики нолики»с

использованием UDP протокола. Клиент «активный», сервер «пассивный».

2. Используемые сетевые сообщения.

Каждый отправляемый программой пакет имеет идентификатор вида пакета и само

сообщение.

В программе использованы следующие 5 видов пакетов:

1) пакет «информация о карте». В его сообщении содержатся карта

игры. При ходе одной стороны передается новая карта и номер хода /Info (i)/.

2) пакет «подтверждение хода». Сообщение содержит те же данные, что

и в 1). отправляется при изменении одной координаты /Info (r)/.

3) пакет «установка и проверка соединения» Установка соединения с

сервером и его проверка /Connect/.

4) пакет «ожидание, соединение и проверка». Ожидание соединения, при

соединении периодическая проверка соединения /Ping (r)/.

5) пакет «запрос на получение информации от сервера» /Info (r)/.

Пакеты 1). – 5). имеют следующий формат.

union packd {

char buff[63]; // buffer

struct pack p; // данные

};

где

struct pack{

char action, step; // тип пакета, номер шага

char matr[4][4]; // карта

} ar;

3. Основные функции программы.

· void initme(){;

//Инициализация клиентского и серверного сокетов.

· void ServerStop(HWND hWnd)

//Освобождение ресурсов, завершение нитей, закрытие сокетов.

· bool clientconnect(HWND hWnd)

//Создание нити соединения клиента с сервером.

· void startserv(HWND hWnd)

//Запуск сервера. Запуск нити для работы с клиентом, проверка наличия связи с

клиентом.

· void putplus(HWND hWnd, char flag,char i, char j)

//Принятие хода клиента, отправка карты серверу (или клиенту).

//Параметр flag имеет следующие значения:

// PLUS – крестик, ZERO – нолик.

// (i,j) – координаты хода.

· DWORD WINAPI ThreadAction_cl(LPVOID param)

· DWORD WINAPI ThreadAction_serv(LPVOID param)

//нити клиента и сервера. Проверяют наличие друг друга (клиента и сервера)

При получении информации о ходе – обновляется карта и посылается

подтверждение.

· DWORD WINAPI ThreadAction_put(LPVOID param)

//Нить для отправки информации о ходе сопернику. Производит периодическую

отправку информации о ходе до получения подтверждения о ходе.

· void drawme(HWND hWnd)

//перерисовка карты в случае хода или получения информации.

· CHAR * get_error_text(int code)

· void err(char * pl)

// выдача сообщений об ошибках.

· int testnew(pack st, pack nd)

// проверка целостности информации из пакета (сравнение прошлой и текущей

карт при получении информации. При отличии карты на одну координату

происходит отправка подтверждения и обновление карты игрока).

4. Процессы.

В процессе работы периодически проверяется наличие связи между клиентом и

сервером (пакеты типа 3 и 4). При ходе игрока отправляется информация о ходе

до получения подтверждения. При отсутствии подтверждения (в рамках

определенного времени – timeout на подтверждение) отправка информации

повторяется периодически до получения подтверждения. Случайная потеря или

повреждение пакета не приведет к некорректности работы т.к. осуществляется

проверка целостности данных.

Программа завершает работу по команде пользователя или при timeout-е.

Диаграммы:

Курсовая: Сетевые крестики нолики

5. Текст программы.

#include "stdafx.h"

#include "resource.h"

#include <winsock2.h>

#include <stdlib.h>

#include <stdio.h>

#define MAX_LOADSTRING 100

#define WSA_ACCEPT (WM_USER + 1)

#define WSA_NETEVENT (WM_USER + 2)

#define VALIDSOCK(s) ((s)>=0)

#define DERROR GetLastError()

#define CLOSEROUTINE(s) closesocket(s)

#define TRETCODE WORD

/*

* Client interaction routine data

*/

typedef struct _THREAD_DATA {

SOCKET client;

struct sockaddr_in address;

} THREAD_DATA, * PTHREAD_DATA;

struct cs {

SOCKET client,server;

} mcs;

struct pack{

char action, step;

char matr[4][4];

} ar;

union packd {

char buff[63];

struct pack p;

};

int tr = 0, trd = 0;

/*

* socket adrress type converter routine

*/

#define SACONV(a) (struct sockaddr *)a

void err(char * pl);

void drawme(HWND hWnd);

void ServerStop(HWND hWnd);

HINSTANCE hInst;

// current instance

TCHAR szTitle[MAX_LOADSTRING];

// The title bar text

TCHAR szWindowClass[MAX_LOADSTRING];

// The title bar text

ATOM

MyRegisterClass(HINSTANCE hInstance);

BOOL

InitInstance(HINSTANCE, int);

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);

bool iamserv = false,started = false, iamclient = false, selected = false,

sstep = false, cstep = true;

SOCKET s,s_cl=0,client=0; /* Client connection socket */;

SOCKADDR_IN dest_sin;

struct sockaddr_in caddr; /* Local socket bind address */

struct sockaddr_in saddr; /* Remote (target) address */

struct sockaddr_in local_cl; /* Local client address */

HANDLE thread,thread_cl,thread_draw, thread_put;

#define SERV_PORT 55555

#define CLNT_PORT 55556

#define PLUS 1

#define ZERO 2

#define SIDE 40

struct timeval tv;

HANDLE finished, finished_cl, finished_draw,finished_put;

CHAR * get_error_text(int code) {

switch (code) {

case (WSANOTINITIALISED): return "Winsock was not initialized";

case (WSAENETDOWN): return "Network subsystem failed";

case (WSAEADDRINUSE): return "local addres already used";

case (WSAEINTR): return "call cancelled";

case (WSAEINPROGRESS): return "operation in progress";

case (WSAEALREADY): return "already connecting";

case (WSAEADDRNOTAVAIL): return "local address not available";

case (WSAEAFNOSUPPORT): return "address family not supported";

case (WSAECONNREFUSED): return "connection refused (port closed)";

case (WSAEFAULT): return "memory access violation";

case (WSAEINVAL): return "invalid socket operation";

case (WSAEISCONN): return "already connected";

case (WSAENETUNREACH): return "network unreachable";

case (WSAENOBUFS): return "no buffer space available";

case (WSAENOTSOCK): return "not a socket";

case (WSAETIMEDOUT): return "timeout";

case (WSAEWOULDBLOCK): return "socket nonblocking, but operation blocks";

case (WSAEACCES): return "broadcast address given";

}

return "Unknown error";

}

int cmpstruct(pack st, pack nd){

int i,j,k=0;

for(i=0; i<=3; i++) {

for(j=0;j<=3;j++) {

if(st.matr[i][j] != nd.matr[i][j]) {

k++;

}

}

}

return(k);

}

int testnew(pack st, pack nd){

int i,j,k=0;

for(i=0; i<=3; i++) {

for(j=0;j<=3;j++) {

if((st.matr[i][j] != nd.matr[i][j]) &&

st.matr[i][j] == 0 && nd.matr[i][j] != 0) {

k = k + 1;

}

}

}

return(k);

}

PTHREAD_DATA dt=NULL;

DWORD WINAPI ThreadAction_serv(LPVOID param) {

union packd p;

memset(&p,0,sizeof(p));

// struct sockaddr addr;

struct sockaddr_in addr;

addr.sin_addr.s_addr = INADDR_ANY;

int size = sizeof(caddr),tmp = -1,e;

fd_set rfds;

struct timeval tv;

HWND hWnd = HWND(param);

FD_ZERO(&rfds);

FD_SET(s, &rfds);

tv.tv_sec = 8192;

tv.tv_usec = 0;

int retval = select(1, &rfds, NULL, NULL, &tv);

while (retval) {

e = recvfrom(s,p.buff, sizeof(p.buff)+1,0,(sockaddr*)&caddr,&size);

caddr.sin_port = htons(CLNT_PORT);

switch(p.p.action){

case('p'):

Sleep(1);

p.p = ar;

e = sendto(s_cl, p.buff, sizeof(p)+1,0,(PSOCKADDR)&caddr, sizeof(caddr));

if (e == -1) err("serv ping send");

started = true;

tmp = testnew(ar,p.p);

if (tmp < 2 && tmp != 0 ){

ar = p.p;

}

drawme(hWnd);

break;

case('i'):

tmp = testnew(ar,p.p);

if (tmp < 2 && tmp != -1) {

ar = p.p;

drawme(hWnd);

p.p.action = 'r';

e = sendto(s_cl, p.buff, sizeof(p)+1,0,(PSOCKADDR)&caddr, sizeof(caddr));

if (e == -1) err("serv reply send");

}

break;

case('r'):

tmp = testnew(ar,p.p);

trd++;

tr = 0;

break;

}

tv.tv_sec = 4 * 60;

retval = select(1, &rfds, NULL, NULL, &tv);

}

MessageBox(NULL,"end of serv die to timeout...","tip",MB_OK);

closesocket(s);

SetEvent(finished);

return(0);

}

DWORD WINAPI ThreadAction_cl(LPVOID param) {

union packd p;

memset(&p,0,sizeof(p));

struct sockaddr_in addr;

int size = sizeof(addr),tmp,e;

fd_set rfds;

struct timeval tv;

HWND hWnd = HWND(param);

lstrcpy(p.buff,"pest string at client start...");

saddr.sin_addr.s_addr = inet_addr("192.168.86.171");

memset(&p,0,sizeof(p));

p.p.action = 'p';

sendto(s, p.buff, sizeof(p)+1,0,(PSOCKADDR)&saddr, sizeof(saddr));

if (e == -1) err("client 1st ping send");

FD_ZERO(&rfds);

FD_SET(s_cl, &rfds);

tv.tv_sec = 4 * 60;

tv.tv_usec = 0;

int retval;

/* SetEvent(finished);

closesocket(s_cl);

return(0);

*/

retval = select(1, &rfds, NULL, NULL, &tv);

while (retval) {

e = recvfrom(s_cl,p.buff,sizeof(p.buff)+1,0,(sockaddr*)&addr,&size);

saddr.sin_port = htons(SERV_PORT);

switch(p.p.action) {

case('p'):

p.p = ar;

e = sendto(s, p.buff, sizeof(p)+1,0,(PSOCKADDR)&saddr, sizeof(saddr));

if (e == -1) err("client ping send");

started = true;

if (testnew(ar,p.p) < 2) {

ar = p.p;

}

drawme(hWnd);

break;

case('i'):

tmp = testnew(ar,p.p);

if (tmp < 2 && tmp != 0 ) {

ar = p.p;

drawme(hWnd);

p.p.action = 'r';

e = sendto(s, p.buff, sizeof(p)+1,0,(PSOCKADDR)&saddr, sizeof(saddr));

if (e == -1) err("client reply error");

}

break;

case('r'):

tmp = testnew(ar,p.p);

trd++;

tr = 0;

if (tmp != 0 ){

MessageBox(NULL,"something wrong","At server got: ",MB_OK);

}

break;

}

memset(&p,0,sizeof(p));

retval = select(1, &rfds, NULL, NULL, &tv);

}

MessageBox(NULL,"end of client (ie timeout...)","tip",MB_OK);

closesocket(s_cl);

SetEvent(finished);

return(0);

}

DWORD WINAPI ThreadAction_put(LPVOID param) {

union packd pa;

/*CString ss;

ss= (char*)param;

pa.buff = ss;

*/

/* char * ss = (char *)param;

for (int i = 0 ; i <= sizeof(pa.buff); i++) {

pa.buff[i] = ss[i];

}

*/ pa.p = ar;

pa.p.action = 'i';

int e;

tr ++;

while (tr >= trd) {

if (! iamserv && iamclient) {

saddr.sin_port = htons(SERV_PORT);

e = sendto(s, pa.buff, sizeof(pa.buff)+1, 0,(PSOCKADDR)&saddr, sizeof(saddr));

} ;

if (iamserv && ! iamclient){

caddr.sin_port = htons(CLNT_PORT);

e = sendto(s_cl, pa.buff, sizeof(pa.buff)+1, 0,(PSOCKADDR)&caddr, sizeof(caddr));

}

Sleep(1);

}

trd = 0; tr = 0;

return(0);

}

void putplus(HWND hWnd, char flag,char i, char j) {

union packd p;

// p.p = ar;

// p.p.action = 'i';

int e, timer;

if (ar.matr[i][j]==0) ar.matr[i][j] = flag;

ar.action = 'i';

p.p = ar;

drawme(hWnd);

CloseHandle(finished_put);

DWORD threadID;

finished_put = CreateEvent(NULL,TRUE,FALSE,NULL);

thread_put = CreateThread(

NULL,65536,ThreadAction_put,(LPVOID)p.buff,CREATE_SUSPENDED,&threadID

);

ResumeThread(thread_put);

return;

// return(true);

}

void drawme(HWND hWnd){

HDC hdc = GetDC(hWnd);

DWORD threadID;

int x,y;

for (x = 1 ; x<=3; x++) {

for(y = 1; y<=3; y++) {

if (ar.matr[x][y] == ZERO) Ellipse(hdc,x*SIDE,y*SIDE,(x+1)*SIDE,(y+1)*SIDE);

// putplus(PLUS,x,y);

if (ar.matr[x][y] == PLUS) {

MoveToEx(hdc,x*SIDE,y*SIDE,NULL);

LineTo(hdc,(x+1)*SIDE,(y+1)*SIDE);

MoveToEx(hdc,(x+1)*SIDE,y*SIDE,NULL);

LineTo(hdc,x*SIDE,(y+1)*SIDE);

}

}

}

// MoveTo(x * side, y* side);

// LineTo((x+1)* side, (y+1)*side);

/* if (x < 4 && x>0 && y < 4 && y > 0) {

Ellipse(hdc,x*side,y*side,(x+1)*side,(y+1)*side);

putplus(PLUS,x,y);

MoveToEx(hdc, x*side,y*side,NULL);

LineTo(hdc,(x+1)*side,(y+1)*side);

MoveToEx(hdc,(x+1)*side,y*side,NULL);

LineTo(hdc,x*side,(y+1)*side);

}

*/

// putminus(x,y);

ReleaseDC(hWnd, hdc);

return;

finished_draw = CreateEvent(NULL,TRUE,FALSE,NULL);

thread_draw = CreateThread(

NULL,65536,ThreadAction_cl,(LPVOID)hWnd,CREATE_SUSPENDED,&threadID

);

ResumeThread(thread_draw);

started=true;

}

DWORD WINAPI ThreadAction_drawme(LPVOID param) {

HDC hdc = GetDC((HWND)param);

Ellipse(hdc,2 * SIDE, 2 * SIDE, (2+1) * SIDE,(2+1) * SIDE);

ReleaseDC((HWND)param, hdc);

SetEvent(finished_draw);

return(2);

}

void initme(){

s = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP);

saddr.sin_family=AF_INET; /* Target address is IP */

saddr.sin_port=htons(SERV_PORT);

saddr.sin_addr.s_addr = INADDR_ANY;

s_cl = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP);

caddr.sin_family = AF_INET;

caddr.sin_addr.s_addr = INADDR_ANY; //= inet_addr("127.168.86.167");

caddr.sin_port = htons(CLNT_PORT);

}

void startserv(HWND hWnd) {

// Handle для Thread'а, используется в Resume/Suspend/Destroy

DWORD threadID;

// ThreadID, используется для

//[13:05:31] <Dalth>

//OpenThread, по-моему, и для некоторых других целей

if (bind(s,SACONV(&saddr),sizeof(saddr))!=0){

MessageBox(NULL,"bind at server error","bind",MB_OK);

};

finished = CreateEvent(NULL,TRUE,FALSE,NULL);

thread = CreateThread(

NULL,65536,ThreadAction_serv,(LPVOID)hWnd,CREATE_SUSPENDED,&threadID

);

ResumeThread(thread);

}

bool clientconnect(HWND hWnd) {

CloseHandle(finished_cl);

DWORD threadID;

int rc = bind(s_cl,SACONV(&caddr),sizeof(caddr));

if ( rc != 0 ) {

}

// here was bug

finished_cl = CreateEvent(NULL,TRUE,FALSE,NULL);

thread_cl = CreateThread(

NULL,65536,ThreadAction_cl,(LPVOID)hWnd,CREATE_SUSPENDED,&threadID

);

ResumeThread(thread_cl);

return(true);

}

void ServerStop(HWND hWnd) {

CloseHandle(finished);

CloseHandle(finished_draw);

CloseHandle(finished_cl);

CloseHandle(finished_put);

started = false;

closesocket(s);

closesocket(s_cl);

}

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR

lpCmdLine,

int nCmdShow){

// TODO: Place code here.

MSG msg;

HACCEL hAccelTable;

// Initialize global strings

LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);

LoadString(hInstance, IDC_SERVE, szWindowClass, MAX_LOADSTRING);

MyRegisterClass(hInstance);

// Perform application initialization:

if (!InitInstance (hInstance, nCmdShow))

{

return FALSE;

}

hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_SERVE);

// Main message loop:

while (GetMessage(&msg, NULL, 0, 0)) {

if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) {

TranslateMessage(&msg);

DispatchMessage(&msg);

}

}

return msg.wParam;

}

ATOM MyRegisterClass(HINSTANCE hInstance)

wcex.hCursor = LoadCursor(NULL, IDC_ARROW);

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) {

HWND hWnd;

hInst = hInstance; // Store instance handle in our global variable

// hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,

// CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, 0, 200, 256, NULL, NULL, hInstance, NULL);

if (!hWnd) {

return FALSE;

}

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

return TRUE;

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

PAINTSTRUCT ps;

HDC hdc;

RECT rt;

int wmId, wmEvent,rc;

TCHAR szHello[MAX_LOADSTRING];

LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);

unsigned char i,j, x,y;

switch (message)

{

case WM_CREATE:

WSADATA WSAData;

// Инициализация и проверка версии Windows Sockets

rc = WSAStartup(MAKEWORD(1, 1), &WSAData);

initme();

if (rc != 0){

MessageBox(NULL, "WSAStartup Error", "Error", MB_OK);

return FALSE;

} else {

return TRUE;

}

case WM_COMMAND:

wmId = LOWORD(wParam);

wmEvent = HIWORD(wParam);

// Parse the menu selections:

switch (wmId)

{

case IDM_ABOUT:

DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);

break;

case IDM_EXIT:

DestroyWindow(hWnd);

break;

case IDM_START:

if (! iamclient) {

selected = true;

iamserv = true;

startserv(hWnd);

memset(&ar,0,sizeof(ar));

ar.step = 1;

} else {

MessageBox(NULL,"I am already client...","tip",MB_OK);

}

break;

case IDM_STOP:

selected = false;

//

if (iamserv) ServerStop(hWnd);

iamserv = false;

iamclient = false;

break;

case IDM_CONNECT:

if ( ! iamserv && clientconnect(hWnd)) {

memset(&ar,0,sizeof(ar));

iamclient = true;

selected = true;

} else {

MessageBox(NULL,"I am already server...","tip",MB_OK);

}

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

break;

case WM_LBUTTONDOWN:

x = (char)(LOWORD(lParam) / SIDE);

y = (char)(HIWORD(lParam) / SIDE );

sstep = ( 2 * (char)(ar.step / 2 ) != (char)ar.step);

if (iamserv && ! iamclient ) {

if (ar.matr[x][y] == 0 ) {

ar.matr[x][y] = PLUS;

ar.step = ar.step + 1;

putplus(hWnd,PLUS,x,y);

}

}

cstep = ( 2 * (char)(ar.step / 2 ) == (char)ar.step);

if (! iamserv && iamclient) {

if (ar.matr[x][y] == 0 ) {

ar.matr[x][y] = ZERO;

ar.step = ar.step + 1;

putplus(hWnd,ZERO,x,y);

}

}

// if ( 2 * (char)(ar.step / 2 )

== (char)ar.step) ar.matr[x][y] = ZERO;

// if ( 2 * (char)(ar.step / 2 )

!= (char)ar.step) ar.matr[x][y] = PLUS;

// drawme(hWnd);

break;

case WM_RBUTTONDOWN:

x = (char)(LOWORD(lParam) / SIDE );

y = (char)(HIWORD(lParam) / SIDE );

ar.matr[x][y] = PLUS;

drawme(hWnd);

break;

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

// TODO: Add any drawing code here...

GetClientRect(hWnd, &rt);

for (i=1;i<=3;i++) {

for (j=1;j<=3;j++) {

Rectangle(hdc,SIDE *i,SIDE*j,SIDE * i + SIDE,SIDE *j + SIDE);

}

}

EndPaint(hWnd, &ps);

break;

case WM_DESTROY:

ServerStop(hWnd);

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return DefWindowProc(hWnd, message, wParam, lParam);

}

LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {

switch (message) {

case WM_INITDIALOG:

return TRUE;

case WM_COMMAND:

if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)

{

EndDialog(hDlg, LOWORD(wParam));

return TRUE;

}

break;

}

return FALSE;

}

{

void err(char * pl) {

MessageBox(NULL,get_error_text(WSAGetLastError()), pl,MB_OK);

}

рефераты Рекомендуем рефератырефераты

     
Рефераты @2011