ОСотчетЧат - Сибирский государственный университет

advertisement
Государственный комитет Российской Федерации по
телекоммуникациям
Сибирский государственный университет
телекоммуникаций и информатики
КУРСОВАЯ РАБОТА
По дисциплине “Операционные системы”
Тема работы
Игра «Многопоточный чат на основе сокетов»
Работу выполнили
студенты 2 курса
группы П-91
Балабко Р. С.
Воронцов С. В.
Скворец В. В.
Работу проверил
Малков Е. А.
Работа защищена
«___» __________2010г.
С оценкой «__________»
Новосибирск 2011
Содержание
2
Цель курсовой работы
3
Поставленные задачи
3
Реализация проекта
4
Листинг
7
2
Цель работы
Целью
нашего
курсового
проекта
являлось
создание
многопользовательского
многопоточного (создание потоков и их синхронизация) чата на основе сокетов (в частности нами
использовался Windows Socket).
Второстепенными целями проекта (поставленными нами) стали реализация клиентской
области при помощи Win API и создание полнофункционально сервера обработчика событий.
Поставленные задачи
- Создание простой в использовании программы-клиента с помощью Win Form и Win API.
- Создание стабильно функционирующего сервера, обменивающегося сообщениями с
программой-клиентом и обрабатывающего описанные в них события.
- Создание канальной системы общения между программой-клиентом и программойсервером используя socket и протокол TCP.
3
Реализация проекта
Программу-клиент ( далее «клиент» ) разрабатывали Балабко Роман, Скворец Вячеслав.
Программу-сервер ( далее «сервер» ) разрабатывали Воронцов Сергей, Скворец Вячеслав.
Реализация программы-сервера:
Cервер функционирует по принципу получил-обработал-отправил.
1)
Получил: Сервер работает в синхронном режиме ( т.е ожидает приема сообщения от
клиента). Т.к для каждого клиента создается отдельный поток, то не возникает ошибки с приемом
сообщения, т.к однозначно известно кто прислал сообщение.
2)
Обработал: два типа сообщений – служебные и пользовательские.
Служебные:
а) «auth nickname password» - авторизация пользователя на сервере. Пользователю
присваивается ник, изменяются его атрибуты в зависимости от статуса на канале.
б) «reg nickname password» - регистрирует nickname на сервере, связывает его с
присланным паролем. Все регистрируемые пользователи хранятся в файлах.
в) «join NameChannel password[optional]» - заходит на канал с именем
NameChannel. Если такой канал не был создан ранее, сервер создает его.
г) «quit NameChannel» - пользователь покидает канал с заданным именем.
д) «creg NameChannel password[optional]» - регистрирует канал NameChannel и,
если указан пароль, связывает его с каналом. Пользователь, регистрирующий канал
становится его администратором.
Пользовательские:
«msg NameChannel Nickname message» - сообщение(message) всем пользователям,
присутствующим в данный момент на канале NameChannel от Nickname.
3)
Отправил: сообщения делятся по типу:
а) «upd NameChannel UserNick(1) Atr(1) … UserNick(n) Atr(n) » - сообщение
генерируется и отсылается пользователю при его заходе на какой-либо канал. В
сообщении указывается название канала, перечисляются присутствующие на нём в
данный момент пользователи и их атрибуты.
б) «jin NameChannel UserNick Atr» - уведомление о входе на канал нового
пользователя, посылается всем пользователям на канал NameChannel.
в) «qit NameChannel UserNick» - уведомление о выходе с канала пользователя,
посылается всем пользователям канала NameChannel.
г) «cng LastUserNick NewUserNick NewAtr» - сообщение генерируется при
изменении статуса пользователя на канале, либо при изменении ника пользователя.
д) «nck NewNickname» - уведомление об изменении имени, приходит только
пользователю совершившему запрос типа «auth» или «reg».
е) «msg NameChannel UserNick message» - сообщение на канале.
ж) «0..9»- уведомление о результате операции, совершённой пользователем.
4
На сервере используется два типа структур: База Клиентов (userinfo), База Каналов (channelBase).
Одна запись клиента выглядит следующим образом:
struct userinfo
{
SOCKET cSocket; // Сокет клиента
sockaddr_in cAddr; // Ip адрес.
struct hostent *hst;
int cAddr_size;
char nickname[32]; // имя пользователя
char LastNickname[32]; // предыдущее имя пользователя
int Attribute; // глобальный атрибут
bool connect; // триггер 1-подключен, 0-отключен
char nameCh[32][128]; // название каналов пользователя.
};
Вся база клиентов выглядит следующим образом :
userinfo ui[N]; - где N это максимальное количество клиентов.
Одна запись канала выглядит следующим образом:
struct channelHead
{
char nameChannel[128]; // название канала
int szUser; // количество пользователей на канале
bool usingCh; // триггер 1-канал активе,0-канал не активен.
bool registration;// триггер 1-канал зарегистрирован,0-канал не зарегистрирован
channelUser *user; // указатель на двухсвязный список содержащий пользователей.
};
struct channelUser
{
int posUser; // хранит позицию клиента в базе клиентов
int Attribute; // хранит атрибут клиента на конкретном канале
channelUser *pNext,*pLost; // указатели на предыдущего и следующего клиента.
};
Вся база каналов выглядит следующим образом:
channelHead channelBase[N]; - где N максимальное число каналов.
Для синхронизации каналов используется массив мютексов.
Также на сервере ведётся архив действий и отображение текущего состояние сервера.
5
Реализация программы-клиента:
Оформление клиентской области
Для создания клиентской области мы использовали некоторые стандартные объекты
Win API, такие как Button, Edit, Static, IpAddress, Combobox и TreeView (вывод каналов и
пользователей, присутствующих на них, переключение между каналами).
Основные компоненты клиентской области:
1) Edit для просмотра истории сообщений. Является недоступным для ввода текста.
2) Edit для ввода сообщения. Ограничен лимитом в 100 символов.
3) IpAddress. Окно для ввода Ip-адреса при подсоединении к серверу. Становится
невидимым после успешного подсоединения.
4) Combobox. Совместно с объектом Button, располагающимся чуть ниже на клиентской
области, реализует меню. Меню состоит из шести пунктов – вход в профиль,
регистрация профиля, выход из профиля, вход в канал, регистрация канала и выход с
канала.
5) TreeView. Реализует дерево просмотра каналов. Родительскими узлами являются
сами каналы, а корневыми узлами для каждого канала являются имена пользователей
присутствующих на нём. Дерево обновляется каждый раз после получения
сообщений типа «upd», «jin», «qit», «cng» и «nck». Переключение между каналами
происходит при помощи щелчка левой кнопкой мыши по имени канала в дереве.
Весь текст из поля истории сообщений при этом заносится в текстовый файл (имя
файла совпадает с именем канала), а в поле истории сообщений записывается текст
из соответствующего каналу, на который совершён переход, файла (если такого
файла нет, то поле истории сообщений становится пустым).
Поля для ввода ника, имени канала и паролей ограничены лимитом в 25 символов.
Объекты типа MessageBox уведомляют пользователя о результате совершённой
операции.
Работа клиентского приложения
Для работы клиента создаётся два потока. В первом потоке происходит получение
сообщений от сервера, после чего обновляется клиентская область. В этом потоке
происходит обновление дерева каналов и истории сообщений. Во втором потоке
происходит получение сообщений от пользователя, после которых выполняются все
остальные действия связанные с изменением клиентской области и по большей части с
отправлением сообщений серверу.
Для того чтобы войти в чат, пользователь должен первым делом подсоединиться к
серверу. После успешного контакта пользователю присваивается стандартный ник
(Default со свободным номером), и пользователь сразу оказывается на общем канале
сервера с названием ALL. В таком режиме пользователь может создавать, но не
регистрировать, каналы, а также заходить на уже созданные, но незапароленные, ну и
соответственно писать сообщения на этих на каналах, активно переключаясь между ними.
Пользователь может зарегистрироваться, либо войти уже под зарегистрированным
профилем. При этом из активного профиля можно совершить выход и войти ещё раз под
другим. Дерево каналов при выходе из профиля очищается, и пользователь вновь
оказывается в такой же ситуации, в какой он был до авторизации.
6
Листинг
Код «программы-сервера»:
pLine.h
void GetNickPass(char *buff,char *nickname,char *password)
{
int val = 0 ;
int i,k=0;
for ( i = 0 ; i < (int)strlen(buff) ; i++ )
{
if (val==2 ) break;
if (buff[i]!=' ' && val == 0 )
{
nickname[k]=buff[i];
k++;
}
if (buff[i]!=' ' && val == 1 )
{
password[k] = buff[i];
k++;
}
if ( val == 0 && buff[i]==' ' ) {nickname[k]=0;k=0;val=1;continue;}
if ( val == 1 && buff[i]==' ' ) {password[k]=0;k=0;val=2;continue;}
}
if (val == 0 )
{
nickname[k-1]=0;
password[0]=0;
}
if (password[k-1] == 10 ) password[k-1]=0;
else password[k]=0;
}
char *RegistrationNickName(char *buff,int posUser)
{
FILE *f;
int i = 0, k=0 ;
char nickname[64];
char password[32];
int val = 0 ;
char filebuff[1024];
filebuff[0]=0;
for (i = 4 ; i < (int)strlen(buff) ; i++ )
{
if (val == 2 ) break;
if ( val == 0 && buff[i]!=' ' )
{
nickname[k] = buff[i];
k++;
}
if ( val == 1 && buff[i]!=' ')
{
password[k] = buff[i];
k++;
}
if ( buff[i]==' ' && val == 0 ) {nickname[k]=0; val++;k=0;continue;}
if ( buff[i]==' ' && val == 1 ) {password[k]=0; val++;k=0;continue;}
}
password[k]=0;
strcpy(filebuff,pathNick);
strcat(filebuff,nickname);
f=fopen(filebuff,"r");
if (f==0 )
{
f=fopen(filebuff,"w");
fprintf(f,"%s",password);
fclose(f);
sprintf(filebuff,"Registration Complete %s\n",nickname );
AddLogFile(logName,filebuff);
printf("Slot[%i] %s->%s\n",posUser,ui[posUser].nickname,nickname);
strcpy(ui[posUser].LastNickname,ui[posUser].nickname);
7
strcpy(ui[posUser].nickname,nickname);
ui[posUser].Attribute = AS_USER ;
SendNewNickname(posUser);
return "0"; // все окей
}
else
{
return
"1"; // такой ник уже занят
}
}
char *AuthNickName(char *buff,int posUser)
{
FILE *f;
char nickname[32];
char password[32];
char psAuth[32];
char filebuff[128];
int i ;
GetNickPass(buff,nickname,password);
strcpy(filebuff,pathNick);
strcat(filebuff,nickname);
f=fopen(filebuff,"r");
if ( f == 0 ) {return "3";} // нет регистрации
fscanf(f,"%s",&psAuth);
if (strcmp(psAuth,password)==0 )
{
for ( i = 0 ; i < 1024 ; i ++ )
{
if (ui[i].connect == true
&& strcmp(nickname,ui[i].nickname)==0 ) return "4"; // уже вошел
}
printf("Slot[%i] %s->%s\n",posUser,ui[posUser].nickname,nickname);
strcpy(ui[posUser].LastNickname,ui[posUser].nickname);
strcpy(ui[posUser].nickname,nickname);
ui[posUser].Attribute = AS_USER ;
SendNewNickname(posUser);
return "0"; // все окей
}
return "2"; // неверный пароль
}
void Logout(int posUser)
{
char v[12];
char name[32];
printf("Slot[%i] %s->",posUser,ui[posUser].nickname);
strcpy(name,"Default");
strcat(name,_itoa(posUser,v,10));
strcpy(ui[posUser].LastNickname,name);
strcpy(ui[posUser].nickname,name);
printf("%s\n",ui[posUser].nickname);
ui[posUser].Attribute= AS_NUSER;
SendNewNickname(posUser);
}
char *ProcLine(char *buff,int posUser,int *only)
{
char bf[128];
int i = 0 ;
int k = 0 ;
*only = -2;
if (strncmp(buff,"reg",3)==0 )
{
strcpy(buff,RegistrationNickName(buff,posUser));
*only = 1 ;
}
if (strncmp(buff,"auth",4)==0 )
{
for ( i = 5 ; i < (int)strlen(buff) ; i ++ )
{
buff[k]=buff[i];
k++;
}
buff[k]=0;
strcpy(buff,AuthNickName(buff,posUser));
*only = 1 ;
}
if (strncmp(buff,"msg",3)==0)
{
8
*only=0;
return buff;
}
if (strncmp(buff,"quit",4)==0 )
{
strcpy(bf, GetNameChannel(buff,5));
QuitUserChannel(bf,posUser);
*only = -1;
}
if (strncmp(buff,"join",4)==0)
{
for ( i = 5 ; i < (int)strlen(buff) ; i ++ )
{
buff[k]=buff[i];
k++;
}
buff[k]=0;
JoinChannel(buff,posUser);
*only = -1 ;
}
if (strncmp(buff,"creg",4)==0)
{
for ( i = 5 ; i < (int)strlen(buff) ; i ++ )
{
buff[k]=buff[i];
k++;
}
buff[k]=0;
RegistrationChannel(buff,posUser);
*only = -1 ;
}
if ( strcmp(buff,"exit")==0)
{
*only = -3 ;
}
if (strcmp(buff,"logout")==0)
{
Logout(posUser);
}
strcat(buff,(char *)&razd);
return buff;
}
connection.h
struct userinfo
{
SOCKET cSocket;
sockaddr_in cAddr;
struct hostent *hst;
int cAddr_size;
char nickname[32];
char LastNickname[32];
int Attribute;
bool connect;
char nameCh[32][128];
};
userinfo ui[N];
void InitUserInfo()
{
int i;
for (i=0;i<1024;i++)ui[i].connect=false;
}
int SearchPosUI()
{
int i;
for (i=0;i<1024;i++)
{
if (ui[i].connect==false ) {ui[i].connect=true; return i ; }
}
return -1;
}
9
void ThreadUser(void *p)
{
int i=0;
int j = 0 ;
int bytes_recv;
char buff[2048];
char nameChannel[128];
int only = 0 ;
bool join = false;
SendNewNickname((int)p);
NewUserChannel("ALL",(int)p,S_USER,1);
while (1)
{
bytes_recv=recv(ui[(int)p].cSocket,&buff[0],sizeof(buff),0);
printf("Slot[%i] -> Message : %s\n",(int)p,buff);
if (strcmp(buff,ui[(int)p].nickname)==0) bytes_recv = -1 ;
if (bytes_recv!=-1) strcpy(buff,ProcLine(buff,(int)p,&only));
if (bytes_recv == -1 || bytes_recv==SOCKET_ERROR || only == -3 )
{
for ( i = 0 ; i < 32 ; i ++ )
{
if ( ui[(int)p].nameCh[i][0] !=0 )
{
QuitUserChannel(ui[(int)p].nameCh[i],(int)p);
}
}
break;
}
if (only == 1 )
{
send(ui[(int)p].cSocket,&buff[0],(int)strlen(buff),0);
if (buff[0]!='0' ) continue;
for (i = 0 ; i < 32 ; i++ )
{
if ( ui[(int)p].nameCh[i][0]!=0)
{
j = SearchChannel(ui[(int)p].nameCh[i]);
if ( channelBase[j].registration == 1 )
ChangeAtributeUser((int)p,j);
strcpy(buff,UpdateChannel(ui[(int)p].nameCh[i],j,3,(int)p));
WaitForSingleObject(hMutexChannel[j],INFINITE);
channelUser *snd = channelBase[j].user ;
while (snd!=0)
{
send(ui[snd>posUser].cSocket,&buff[0],(int)strlen(buff),0);
snd=snd->pNext;
}
ReleaseMutex(hMutexChannel[j]);
}
}
strcpy(ui[(int)p].LastNickname,ui[(int)p].nickname);
}
if (only == 0 )
{
strcpy(nameChannel,GetNameChannel(buff,4));
for (i = 0 ; i < 32 ; i ++ ) if
(strcmp(ui[(int)p].nameCh[i],nameChannel)==0 ) {join = true ; break;}
if ( join == false ) continue;
i = SearchChannel(nameChannel);
if ( i == -1 ) continue;
WaitForSingleObject(hMutexChannel[j],INFINITE);
channelUser *snd = channelBase[i].user ;
strcat(buff,(char *)&razd);
while ( snd!=0 )
{
send(ui[snd->posUser].cSocket,&buff[0],(int)strlen(buff),0);
snd=snd->pNext;
}
ReleaseMutex(hMutexChannel[j]);
}
}
10
printf ("Slot:[%d] +%s [%s] connect close\n",(int)p,(ui[(int)p].hst)?ui[(int)p].hst>h_name:"",inet_ntoa(ui[(int)p].cAddr.sin_addr));
sprintf (buff,"+%s [%s] connect close\n",(ui[(int)p].hst)?ui[(int)p].hst>h_name:"",inet_ntoa(ui[(int)p].cAddr.sin_addr));
AddLogFile(logName,buff);
closesocket(ui[(int)p].cSocket);
ui[(int)p].connect=false;
}
void workServer()
{
InitUserInfo();
SOCKET tSocket ;
sockaddr_in tAddr;
int tAddr_size = sizeof(tAddr);
int pos;
char buff[1024];
strcpy(channelBase[0].nameChannel,"ALL");
channelBase[0].registration = true ;
channelBase[0].szUser = 0;
channelBase[0].user = 0 ;
channelBase[0].usingCh = true;
while (tSocket=accept(sSocket,(sockaddr *)&tAddr,&tAddr_size))
{
pos = SearchPosUI();
ui[pos].hst=gethostbyaddr((char *)&tAddr.sin_addr.s_addr,4,AF_INET);
ui[pos].connect = true ;
ui[pos].cAddr_size = tAddr_size;
ui[pos].cAddr = tAddr;
ui[pos].cSocket = tSocket;
ui[pos].Attribute= AS_NUSER ;
sprintf(buff,"Deafailt%i",pos);
strcpy(ui[pos].nickname,buff);
strcpy(ui[pos].LastNickname,buff);
printf ("Slot:[%d] +%s [%s] new connect\n",pos,(ui[pos].hst)?ui[pos].hst>h_name:"",inet_ntoa(ui[pos].cAddr.sin_addr));
sprintf(buff,"+%s [%s] new connect\n",(ui[pos].hst)?ui[pos].hst>h_name:"",inet_ntoa(ui[pos].cAddr.sin_addr));
AddLogFile(logName,buff);
_beginthread(ThreadUser,0,(void *)pos);
}
}
head.h
#define AS_NUSER -1
#define AS_USER 0
#define S_USER 0
#define S_MDR 1
#define S_ADMN 2
#define N 1024
#define rzd 11
char razd = rzd ;
char pathNick[] = "BaseNickname/";
char pathChannel[] = "BaseChannel/";
HANDLE hMutexChannel[N];
struct channelUser
{
int posUser;
int Attribute;
channelUser *pNext,*pLost;
};
struct channelHead
{
char nameChannel[128];
int szUser;
bool usingCh;
bool registration;
channelUser *user;
};
channelHead channelBase[N];
int NewUserChannel(char *,int,int,int);
void AddLogFile(char *,char *);
char *ProcLine(char *,int,int *);
char *GetNameChannel(char *,int);
11
char *UpdateChannel(char *,int,int,int);
void QuitUser(int);
char *QuitUserChannel(char *,int);
int SearchChannel(char *);
void JoinChannel(char *,int);
void RegistrationChannel(char *,int);
void ChangeAtributeUser(int,int);
void SendNewNickname(int);
Channel.h
void InitChannel()
{
int i;
for ( i = 0 ; i < 1024 ; i ++ )
{
channelBase[i].usingCh = false ;
}
}
int SearchChannel(char *nameCh)
{
int i;
for ( i = 0 ; i < 1024 ; i ++ )
{
if ( strcmp(nameCh,channelBase[i].nameChannel)==0) return i;
}
return -1;
}
void ChangeAtributeUser(int posUser,int i)
{
char buff[32];
char filebuff[128];
int atr = -1;
FILE *f;
strcpy(filebuff,pathChannel);
strcat(filebuff,channelBase[i].nameChannel);
f = fopen(filebuff,"r");
if (f == 0 ) return ;
fgets(buff,32,f);
if ( buff[0]==10 ) buff[0]=0;
while (feof(f)==false)
{
fscanf(f,"%s %i",&buff,&atr);
if ( strcmp(buff,ui[posUser].nickname)==0)
{
channelUser *tm = channelBase[i].user;
while (tm!=0)
{
if (tm->posUser == posUser ) {fclose(f);tm->Attribute = atr
;return; }
tm=tm->pNext;
}
fclose(f);
}
}
fclose(f);
}
char *GetNameChannel(char *buff,int i)
{
char name[128];
int k = 0 ;
for (i ; i < strlen(buff) ; i ++ )
{
if (buff[i]==' ' ) break;
name[k] = buff[i];
k++;
}
if ( i == (int)strlen(buff) ) name[k-1] = 0;
else name[k]=0;
return name;
}
void SetChannelNameUser(char *nameCh,int posUser)
{
int i;
for (i = 0 ; i < 32 ; i++ )
12
{
if (ui[posUser].nameCh[i][0]==0 )
{
strcpy(ui[posUser].nameCh[i],nameCh);
return;
}
}
}
void ClearChannelNameUser(char name[],int posUser)
{
char nameCh[128];
strcpy(nameCh,name);
int i;
for (i = 0 ; i < 32 ; i++ )
{
if (strcmp(nameCh,ui[posUser].nameCh[i])==0 )
{
ui[posUser].nameCh[i][0]=0;
strcpy(name,nameCh);
break;
}
}
return ;
}
void SendUserChannel(int i,int posUser,int trg)
{
channelUser *tm =channelBase[i].user;
WaitForSingleObject(hMutexChannel,INFINITE);
char buff[2048];
char buffuser[2048];
strcpy(buffuser,UpdateChannel(channelBase[i].nameChannel,i,0,posUser));
strcpy(buff,UpdateChannel(channelBase[i].nameChannel,i,trg,posUser));
while (tm!=0)
{
if ( tm->posUser == posUser )
{
send(ui[tm->posUser].cSocket,&buffuser[0],(int)strlen(buffuser),0);
}
else
{
send(ui[tm->posUser].cSocket,&buff[0],(int)strlen(buff),0);
}
tm=tm->pNext;
}
ReleaseMutex(hMutexChannel);
}
int NewUserChannel(char *nameCh,int posUser,int atr,int RegCh)
{
int i ;
for ( i = 0 ; i < 1024 ; i ++ )
{
if (channelBase[i].usingCh == true &&
strcmp(nameCh,channelBase[i].nameChannel)==0)
{
WaitForSingleObject(hMutexChannel[i],INFINITE);
channelUser *tm = new channelUser;
tm->posUser = posUser;
tm->Attribute = atr;
tm->pLost = 0 ;
tm->pNext = channelBase[i].user ;
channelBase[i].szUser ++ ;
channelBase[i].registration = RegCh;
if(channelBase[i].user == NULL )
{
channelBase[i].user = new channelUser;
channelBase[i].user = tm ;
printf("Slot[%i] new user channel [%s] , size Channel [%i] ,
regChannel [%i]\n",i,nameCh,channelBase[i].szUser,channelBase[i].registration);
SetChannelNameUser(nameCh,posUser);
ReleaseMutex(hMutexChannel[i]);
SendUserChannel(i,posUser,1);
return i;
}
channelBase[i].user->pLost = tm ;
channelBase[i].user = tm;
printf("Slot[%i] new user channel [%s] , size Channel [%i] , regChannel
[%i]\n",i,nameCh,channelBase[i].szUser,channelBase[i].registration);
13
SetChannelNameUser(nameCh,posUser);
ReleaseMutex(hMutexChannel[i]);
SendUserChannel(i,posUser,1);
return i;
}
}
for ( i = 0 ; i < 1024 ; i ++ )
{
if (channelBase[i].usingCh == false ) break;
}
hMutexChannel[i] = CreateMutex(NULL,FALSE,NULL);
channelBase[i].usingCh = true;
channelBase[i].registration = RegCh ;
strcpy(channelBase[i].nameChannel,nameCh);
channelBase[i].szUser = 1 ;
channelBase[i].user = new channelUser ;
channelBase[i].user->Attribute = atr;
channelBase[i].user->pLost = 0 ;
channelBase[i].user->pNext = 0 ;
channelBase[i].user->posUser = posUser;
if (RegCh==0) printf("Slot[%i] new not registred channel [%s]\n",i,nameCh);
else printf("Slot[%i] new user channel [%s] , size Channel [%i] , regChannel
[%i]\n",i,nameCh,channelBase[i].szUser,channelBase[i].registration);
SetChannelNameUser(nameCh,posUser);
SendUserChannel(i,posUser,1);
return i;
}
int AddUserChannel(char *nameCh,char *password,int posUser)
{
char buff[32];
char filebuff[128];
int atr = -1;
int len = 0 ;
FILE *f;
strcpy(filebuff,pathChannel);
strcat(filebuff,nameCh);
f = fopen(filebuff,"r");
if ( f!=0)
{
if (ui[posUser].Attribute == AS_NUSER )
{
fclose(f);
return -1;
}
fgets(buff,32,f);
len = strlen(buff);
if ( buff[0]==10 ) buff[0]=0;
else buff[len-1] = 0 ;
if ( strcmp(password,buff) !=0 )
{
fclose(f);
return -1;
}
while (feof(f)==false)
{
fscanf(f,"%s %i",&buff,&atr);
if ( strcmp(buff,ui[posUser].nickname)==0)
{
fclose(f);
return NewUserChannel(nameCh,posUser,atr,1);
}
}
fclose(f);
return NewUserChannel(nameCh,posUser,S_USER,1);
}
return NewUserChannel(nameCh,posUser,S_USER,0);
}
void RegistrationChannel(char *buff,int posUser)
{
FILE *f;
char sndErr[10];
char filebuff[1024];
char nameCh[32];
char passCh[32];
char upd[2048];
int i = 0 ;
14
GetNickPass(buff,nameCh,passCh);
if (ui[posUser].Attribute == AS_NUSER )
{
strcpy(sndErr,"8");
strcat(sndErr,(char *)&razd);
send(ui[posUser].cSocket,sndErr,strlen(sndErr),0);
return;
}
strcpy(filebuff,pathChannel);
strcat(filebuff,nameCh);
f=fopen(filebuff,"r");
if ( f!=0)
{
strcpy(sndErr,"7");
strcat(sndErr,(char *)&razd);
send(ui[posUser].cSocket,sndErr,strlen(sndErr),0);
return ;
}
f=fopen(filebuff,"w");
fprintf(f,"%s\n",passCh);
fprintf(f,"%s %i\n",ui[posUser].nickname,S_ADMN);
printf ("Registration Channel [%s] pass [%s]\n",nameCh,passCh);
fclose(f);
i = SearchChannel(nameCh);
WaitForSingleObject(hMutexChannel[i],INFINITE);
channelBase[i].registration = 1 ;
ChangeAtributeUser(posUser,i);
strcpy(sndErr,"0");
strcat(sndErr,(char *)&razd);
send(ui[posUser].cSocket,sndErr,strlen(sndErr),0);
channelUser *tm = channelBase[i].user ;
strcpy(upd,UpdateChannel(channelBase[i].nameChannel,i,3,posUser));
while (tm!=0)
{
send(ui[tm->posUser].cSocket,upd,strlen(upd),0);
tm=tm->pNext;
}
ReleaseMutex(hMutexChannel[i]);
sprintf(buff,"Channel %s registred, ADMN - %s",nameCh,ui[posUser].nickname);
AddLogFile(logName,buff);
return ;
}
char *QuitUserChannel(char *nameCh,int posUser)
{
int i = SearchChannel(nameCh);
channelUser * tm ;
WaitForSingleObject(hMutexChannel[i],INFINITE);
tm = channelBase[i].user ;
while (tm!=0)
{
if ( tm->posUser == posUser )
{
if ( tm->pLost == 0 )
{
channelBase[i].user = tm->pNext ;
if ( channelBase[i].user != 0 )
channelBase[i].user->pLost = 0 ;
}
else
{
if (tm->pNext == 0 ) tm->pLost->pNext = 0 ;
else
{
tm->pLost->pNext = tm->pNext;
tm->pNext->pLost = tm->pLost;
}
}
channelBase[i].szUser--;
break;
}
tm=tm->pNext;
}
ReleaseMutex(hMutexChannel[i]);
ClearChannelNameUser(channelBase[i].nameChannel,posUser);
if (channelBase[i].szUser == 0 && i!=0 )
{
15
CloseHandle(hMutexChannel[i]);
channelBase[i].usingCh = false ;
printf("Slot[%i] channel [%s] quit [%s] szCh[%i] UsingCh [%i] RegCh [%i]
\n",i,channelBase[i].nameChannel,ui[posUser].nickname,channelBase[i].szUser,channelBase[i].usingC
h,channelBase[i].registration);
return 0;
}
printf("Slot[%i] channel [%s] quit [%s] szCh[%i] UsingCh [%i] RegCh [%i]
\n",i,channelBase[i].nameChannel,ui[posUser].nickname,channelBase[i].szUser,channelBase[i].usingC
h,channelBase[i].registration);
SendUserChannel(i,posUser,2);
return 0;
}
char *UpdateChannel(char *nameCh,int i,int trg,int posUser)
{
WaitForSingleObject(hMutexChannel[i],INFINITE);
char v[12];
char buff[2048];
int len ;
if ( trg == 0 )
{
strcpy(buff,"upd ");
strcat(buff,nameCh);
len = strlen(buff);
channelUser *tm = channelBase[i].user;
while (tm!=0)
{
buff[len]=' ';
buff[len+1]=0;
strcat(buff,ui[tm->posUser].nickname);
len = strlen(buff);
buff[len]=' ';
buff[len+1]=0;
strcat(buff,_itoa(tm->Attribute,v,10));
len = strlen(buff);
tm=tm->pNext;
}
strcat(buff,(char *)&razd);
}
if ( trg == 1 )
{
channelUser *tm = channelBase[i].user;
while (tm->posUser!=posUser) {tm=tm->pNext;}
strcpy(buff,"jin ");
strcat(buff,nameCh);
strcat(buff," ");
strcat(buff,ui[posUser].nickname);
strcat(buff," ");
strcat(buff,_itoa(tm->Attribute,v,10));
strcat(buff,(char *)&razd);
}
if ( trg == 2 )
{
strcpy(buff,"qit ");
strcat(buff,nameCh);
strcat(buff," ");
strcat(buff,ui[posUser].nickname);
strcat(buff,(char *)&razd);
}
if ( trg == 3 )
{
strcpy(buff,"cng ");
strcat(buff,nameCh);
strcat(buff," ");
strcat(buff,ui[posUser].LastNickname);
strcat(buff," ");
channelUser *tm = channelBase[i].user;
while (tm->posUser!=posUser) {tm=tm->pNext;}
strcat(buff,ui[posUser].nickname);
strcat(buff," ");
strcat(buff,_itoa(tm->Attribute,v,10));
strcat(buff,(char *)&razd);
}
ReleaseMutex(hMutexChannel[i]);
return buff;
}
void JoinChannel(char *buff,int posUser)
{
16
char nameCh[32];
char password[32];
int i;
GetNickPass(buff,nameCh,password);
for (i = 0 ; i < 32 ; i ++ )
if (strcmp(ui[posUser].nameCh[i],nameCh)==0 ) return;
if (AddUserChannel(nameCh,password,posUser) == -1 )
{
strcpy(nameCh,"6");
strcat(nameCh,(char *)&razd);
send(ui[posUser].cSocket,nameCh,(int)strlen(nameCh),0);
}
}
void SendNewNickname(int posUser)
{
char filebuff[1024];
strcpy(filebuff,"nck ");
strcat(filebuff,ui[posUser].nickname);
strcat(filebuff,(char *)&razd);
send(ui[posUser].cSocket,&filebuff[0],strlen(filebuff),0);
}
workingServer.h
int StartServer(int sPORT)
{
char wsaData[1024];
if (WSAStartup(0x0202,(WSADATA *)&wsaData))
{
printf ("Error WSAStartup %d\n",WSAGetLastError());
AddLogFile(logName, "Error WSAStartup \n" );
WSACleanup();
return -1;
}
else AddLogFile(logName, " WSAStartup OK \n" );
if ((sSocket=socket(AF_INET,SOCK_STREAM,0))<0)
{
printf ("Error Socket %d\n",WSAGetLastError());
AddLogFile(logName, "Error Socket \n" );
WSACleanup();
return -2;
}
else AddLogFile(logName, "Socket OK \n" );
sAddres.sin_port = htons(sPORT);
sAddres.sin_family = AF_INET;
sAddres.sin_addr.s_addr = 0 ;
if(bind(sSocket,(sockaddr *)&sAddres,sizeof(sAddres)) )
{
printf("Error bind %d\n",WSAGetLastError());
AddLogFile(logName, "Error bind \n" );
closesocket(sSocket);
WSACleanup();
return -3;
}
else AddLogFile(logName,"bind OK \n");
if ( listen(sSocket,0x100) )
{
printf("Error listen %d\n",WSAGetLastError());
AddLogFile(logName, "Error listen \n" );
closesocket(sSocket);
WSACleanup();
return -4;
}
else AddLogFile(logName,"Listen OK \n");
PrintTime();
AddLogFile(logName,"Server started\n");
printf (":Server started\n");
return 0;
}
int EndServer()
{
closesocket(sSocket);
AddLogFile(logName,"Close Socket\n");
WSACleanup();
17
AddLogFile(logName,"Close WSA\n");
PrintTime();
AddLogFile(logName,"Server Close\n" );
return 0;
}
logFile.h
void AddLogFile(char *FileName,char *message)
{
FILE *f;
SYSTEMTIME st;
char buff[1024];
f=fopen(FileName,"a+");
GetSystemTime(&st);
sprintf(buff,"%d.%d.%d ",st.wHour,st.wMinute,st.wSecond);
fwrite((char *)&buff,strlen(buff),1,f);
fwrite(message,strlen(message),1,f);
fclose(f);
}
index.cpp
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#include <process.h>
#include <conio.h>
#include "head.h"
SOCKET sSocket;
sockaddr_in sAddres;
void PrintTime();
char baseName[]="base.txt";
char logName[]="log12.txt";
#include "connection.h"
#include "logFile.h"
#include "workingServer.h"
#include "pLine.h"
#include "Channel.h"
void PrintTime()
{
SYSTEMTIME st;
GetSystemTime(&st);
printf("%d.%d.%d",st.wHour,st.wMinute,st.wSecond);
}
int main (int argc,char *argv)
{
if (StartServer(1952) !=
workServer();
Sleep(1000*10);
EndServer();
_getch();
return 0;
}
0 ) return -1;
18
Код «программы-клиента»:
Client.h
#include
#include
#include
#include
#include
<stdio.h>
<process.h>
<winsock2.h>
<windows.h>
<conio.h>
#define MY_PORT 1952
#define maxNick 25
#define sim 11
void TreeRedraw(int flag);
void MessagePrint();
int GetUserName(char *name, int count);
void STS(char *msg);
void GMS(void *p);
int Connecting(char *IpAddress, HWND hWnd);
SOCKET serverSocket, ClientSocket;
sockaddr_in LocalAddr, ClientAddr;
int ClientAddr_size = sizeof(ClientAddr);
char *message;
int answer;
char bufer[2048];
HWND hwnd;
struct hostent *hst;
int bytes_recv;
char *nick = new char[maxNick+1];
int separation(char *in, char *out, int count){
int i=count;
while(in[i]!=sim){
out[i-count]=in[i];
i++;
}
out[i-count]=0;
return i;
}
void STS(char *msg){
send(serverSocket,msg,strlen(msg)+1,0);
}
void GMS(void *p){
int i;
while((bytes_recv=recv(serverSocket,&bufer[0],sizeof(bufer)-1,0))!=SOCKET_ERROR){
bufer[bytes_recv]=0;
i=-1;
message = new char [2048];
do{
i=separation(bufer,message,i+1);
switch(message[0]){
case 'u':
TreeRedraw(0);
break;
case 'j':
TreeRedraw(1);
break;
case 'q':
TreeRedraw(2);
break;
case 'c':
19
TreeRedraw(3);
break;
case 'm':
MessagePrint();
break;
case 'n':
GetUserName(nick,4);
break;
case 48: case 49: case 50: case 51: case 52: case 53: case 54: case
55: case 56 :
answer=atoi(message);
break;
}
}
while(bufer[i+1]!=0);
delete[] message;
}
}
int Connecting(char *IpAddress, HWND hWnd){
hwnd=hWnd;
if (WSAStartup(0x0202,(WSADATA *) &bufer)){
WSACleanup();
return 1;
}
if ((serverSocket=socket(AF_INET,SOCK_STREAM,0))<0){
WSACleanup();
return 1;
}
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_port = htons(MY_PORT);
LocalAddr.sin_addr.s_addr = 0 ;
if (inet_addr(IpAddress)!=INADDR_NONE)
LocalAddr.sin_addr.s_addr = inet_addr(IpAddress);
else
if (hst = gethostbyname (IpAddress))
((unsigned long *)&LocalAddr.sin_addr)[0]=((unsigned long **)hst>h_addr_list)[0][0];
else{
closesocket(serverSocket);
WSACleanup();
return 1;
}
if (connect(serverSocket,(sockaddr *)&LocalAddr,sizeof(LocalAddr)))
return 1;
_beginthread(GMS,NULL,NULL);
return 0;
}
ClientAreal.cpp
#include
#include
#include
#include
#define
#define
#define
#define
#define
#define
#define
#define
#define
<stdio.h>
"Client.h"
<windows.h>
<commctrl.h>
LogEdit 1
MsgEdit 2
LoginEdit 3
PswdEdit 4
MemBtn 5
DoBtn 6
SndBtn 7
ExitBtn 8
ChnEdit 9
20
#define
#define
#define
#define
#define
#define
#define
#define
ChpEdit 10
Static 11
ComboBox 12
IpAdr 13
CnctBtn 14
TreeView 15
Time 17
Static2 18
#define
#define
#define
#define
#define
#define
maxMsg 100
maxNick 25
stringLength maxMsg+maxNick*2+10
maxChannels 30
maxUsers 200
maxLog 30000
LRESULT CALLBACK MyWndProc(HWND, UINT, WPARAM, LPARAM);
HTREEITEM ChannelAdd(char *channelName);
void UserAdd(char *userName, HTREEITEM hRoot);
HTREEITEM GetTreeItem(LPTV_ITEM item, HTREEITEM hRoot);
int GetChannelName(char *name);
int GetUserName(char *name, int count);
int GetMessage(char *msg, int count);
void TreeRedraw(int flag);
char *log = new char [maxLog];
HTREEITEM SELECT;
HDC hdc;
RECT rt;
HWND hWnd;
HWND hLog, hMsg, hNick, hPas1, hMem, hPas2, hChnl, hDo;
HWND hSnd, hExit, hCnct;
HWND hTree, hIp, hCombo, hTime, hStatic, hStatic2;
int TransSwitch=0;
HTREEITEM ChannelAdd(char *channelName){
TV_ITEM item;
HTREEITEM hRoot;
LPTV_INSERTSTRUCT lPis = new TV_INSERTSTRUCT;
item.mask=TVIF_TEXT;
item.pszText=channelName;
item.cChildren=1;
item.cchTextMax=25;
lPis->hInsertAfter=TVI_SORT;
lPis->hParent=TVI_ROOT;
lPis->item=item;
hRoot=TreeView_InsertItem(hTree,lPis);
return hRoot;
}
void UserAdd(char *userName, HTREEITEM hRoot){
TV_ITEM item;
LPTV_INSERTSTRUCT lPis = new TV_INSERTSTRUCT;
item.mask=TVIF_TEXT;
item.pszText=userName;
item.cChildren=0;
item.cchTextMax=40;
lPis->hInsertAfter=TVI_SORT;
lPis->hParent=hRoot;
lPis->item=item;
TreeView_InsertItem(hTree,lPis);
}
HTREEITEM GetTreeItem(LPTV_ITEM item, HTREEITEM hRoot){
if (hRoot==NULL)
hRoot=TreeView_GetSelection(hTree);
item->hItem = hRoot;
21
item->mask = TVIF_TEXT;
item->pszText=new char[50];
item->cchTextMax=50;
TreeView_GetItem(hTree,item);
return hRoot;
}
int GetChannelName(char *name){
int i=4;
do{
name[i-4]=message[i];
i++;
}
while(message[i]!=' ');
name[i-4]=0;
return i;
}
int GetUserName(char *name, int count){
int i=count;
char *buf = new char [25];
do{
buf[i-count]=message[i];
i++;
}
while((message[i]!=' ') && (message[i]!=0));
buf[i-count]=0;
switch(message[i+1]){
case 48:
if ((message[i+2]==' ') || (message[i+2]==0))
sprintf(name,"%s [User]",buf);
else{
strcpy(name,buf);
i-=2;
}
break;
case 49:
if ((message[i+2]==' ') || (message[i+2]==0))
sprintf(name,"%s [Moder]",buf);
else{
strcpy(name,buf);
i-=2;
}
break;
case 50:
if ((message[i+2]==' ') || (message[i+2]==0))
sprintf(name,"%s [Admin]",buf);
else{
strcpy(name,buf);
i-=2;
}
break;
default:
strcpy(name,buf);
i-=2;
}
delete[] buf;
return i+2;
}
int GetMessage(char *msg, int count){
int i=count;
do{
msg[i-count]=message[i];
i++;
}
while((message[i]!=0));
msg[i-count]='\n';
msg[i-count+1]=0;
return i;
22
}
void TreeRedraw(int flag){
LPTV_ITEM item = new TV_ITEM;
HTREEITEM hRoot=TreeView_GetChild(hTree,TVI_ROOT), hBuf;
int i;
char *string = new char [50];
TransSwitch=1;
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
GetTreeItem(item, NULL);
i=GetChannelName(string);
if (flag==0){
hRoot=ChannelAdd(string);
if (TreeView_GetSelection(hTree)==NULL)
SELECT=hRoot;
TransSwitch=0;
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
}
else
while(strcmp(item->pszText,string)!=0){
SendMessage(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
hRoot=TreeView_GetNextVisible(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
hRoot=GetTreeItem(item, NULL);
}
switch(flag){
case 0:
do{
i=GetUserName(string,i+1);
UserAdd(string,hRoot);
}
while(message[i]!=0);
SendMessage(hTree, TVM_EXPAND, TVE_EXPAND, (LPARAM)hRoot);
SendMessage(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
break;
case 1:
i=GetUserName(string,i+1);
UserAdd(string,hRoot);
hRoot=TreeView_GetParent(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
break;
case 2:
i=GetUserName(string,i+1);
hRoot=TreeView_GetChild(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
hRoot=GetTreeItem(item,NULL);
while(strncmp(item->pszText,string,strlen(string))!=0){
SendMessage(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
hRoot=TreeView_GetNextVisible(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
hRoot=GetTreeItem(item,NULL);
}
SendMessage(hTree, TVM_DELETEITEM, NULL, (LPARAM)hRoot);
hRoot=TreeView_GetParent(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
break;
case 3:
hBuf=hRoot;
i=GetUserName(string,i+1);
hRoot=TreeView_GetChild(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
hRoot=GetTreeItem(item,NULL);
while(strncmp(item->pszText,string,strlen(string))!=0){
SendMessage(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
hRoot=TreeView_GetNextVisible(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
hRoot=GetTreeItem(item,NULL);
23
}
SendMessage(hTree, TVM_DELETEITEM, NULL, (LPARAM)hRoot);
i=GetUserName(string,i+1);
hRoot=hBuf;
UserAdd(string,hRoot);
break;
}
TransSwitch=0;
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)SELECT);
delete[] string;
delete item;
}
void MessagePrint(){
FILE *f;
LPTV_ITEM item = new TV_ITEM;
HTREEITEM hRoot=TreeView_GetChild(hTree,TVI_ROOT);
int i, nLen;
char *string1 = new char [maxMsg+maxNick*2+10];
char *string2 = new char [maxMsg+maxNick*2+10];
TransSwitch=1;
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
GetTreeItem(item,NULL);
i=GetChannelName(string1);
while(strcmp(item->pszText,string1)!=0){
SendMessage(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
hRoot=TreeView_GetNextVisible(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
hRoot=GetTreeItem(item,NULL);
}
ZeroMemory(string1,strlen(string1));
i=GetUserName(string1,i+1);
sprintf(string2,"%s : ",string1);
ZeroMemory(string1,strlen(string1));
i=GetMessage(string1,i+1);
strcat(string2,string1);
if (hRoot==SELECT){
nLen = GetWindowTextLength (hLog);
SendMessage (hLog, EM_SETSEL, nLen, nLen);
SendMessage (hLog, EM_REPLACESEL, 0, (LPARAM)string2);
}
else{
sprintf(string1,"%s.chnl",item->pszText);
f=fopen(string1,"a+");
fprintf(f,"%s",string2);
fclose(f);
}
SetWindowText(hMsg, (LPCSTR)"");
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)SELECT);
SendMessage(hMsg ,WM_ACTIVATE, WA_ACTIVE, NULL);
TransSwitch=0;
delete item;
delete[] string1;
delete[] string2;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){
MSG msg;
WNDCLASS wc;
LPCSTR lpszAppName="Client areal ver. 1";
BOOL ret;
HTREEITEM hRoot;
wc.lpszClassName = lpszAppName;
wc.hInstance=hInstance;
wc.lpfnWndProc = (WNDPROC)MyWndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
24
wc.hIcon = 0;
wc.lpszMenuName
= 0;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+7);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
if(!RegisterClass(&wc))
return 0;
hWnd = CreateWindow(lpszAppName, lpszAppName, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX | (WS_MAXIMIZEBOX) &~(WS_THICKFRAME), 100, 100, 610, 500, NULL, NULL, hInstance,
NULL);
hLog = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, "edit", "", WS_CHILD |
WS_VISIBLE | ES_READONLY |
ES_MULTILINE | WS_DLGFRAME | WS_VSCROLL , 20, 50, 300, 300, hWnd, (HMENU)LogEdit,
hInstance, NULL);
hMsg = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, "edit", "Enter the message",
WS_CHILD | WS_VISIBLE | ES_MULTILINE |
WS_DLGFRAME | WS_VSCROLL, 20, 360, 300, 60, hWnd, (HMENU)MsgEdit, hInstance,
NULL);
SendMessage (hMsg, EM_LIMITTEXT, maxMsg, NULL);
hNick = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, "edit", "Nickname", WS_CHILD |
WS_VISIBLE | ES_AUTOHSCROLL,480, 30, 100, 20, hWnd, (HMENU)LoginEdit, hInstance, NULL);
SendMessage (hNick, EM_LIMITTEXT, maxNick, NULL);
hPas1 = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, "edit", "Password", WS_CHILD |
WS_VISIBLE | ES_PASSWORD | ES_AUTOHSCROLL, 480, 55, 100, 20, hWnd, (HMENU)PswdEdit, hInstance,
NULL);
SendMessage (hPas1, EM_LIMITTEXT, maxNick, NULL);
hSnd = CreateWindow("BUTTON", "Send", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON , 350, 360,
80, 50, hWnd, (HMENU)SndBtn, hInstance, NULL);
hExit = CreateWindow("BUTTON", "Exit", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 20, 425,
100, 30, hWnd, (HMENU)ExitBtn, hInstance, NULL);
hChnl = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, "edit", "Channel name",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,350, 90, 120, 25, hWnd, (HMENU)ChnEdit, hInstance, NULL);
SendMessage (hChnl, EM_LIMITTEXT, maxNick, NULL);
hPas2 = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE, "edit", "", WS_CHILD |
WS_VISIBLE | ES_PASSWORD | ES_AUTOHSCROLL,475, 90, 105, 25, hWnd, (HMENU)ChpEdit, hInstance,
NULL);
SendMessage (hPas2, EM_LIMITTEXT, maxNick, NULL);
hIp = CreateWindow(WC_IPADDRESS, NULL, WS_CHILD | WS_VISIBLE, 20, 10, 150, 25, hWnd,
(HMENU)IpAdr, hInstance, NULL);
SendMessage(hIp, IPM_SETADDRESS, NULL, MAKEIPADDRESS(192,168,0,1));
hCnct = CreateWindow("BUTTON", "To connect", WS_CHILD | WS_VISIBLE, 175, 10, 145, 25,
hWnd, (HMENU)CnctBtn, hInstance, NULL);
hCombo = CreateWindow("COMBOBOX", "", WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST |
WS_DLGFRAME, 340, 30, 135, 150, hWnd, (HMENU)ComboBox, hInstance, NULL);
SendMessage(hCombo, CB_ADDSTRING, NULL, (LPARAM)"Log in");
SendMessage(hCombo, CB_ADDSTRING, NULL, (LPARAM)"To be registred");
SendMessage(hCombo, CB_ADDSTRING, NULL, (LPARAM)"Log out");
SendMessage(hCombo, CB_ADDSTRING, NULL, (LPARAM)"Channel enter");
SendMessage(hCombo, CB_ADDSTRING, NULL, (LPARAM)"Channel registration");
SendMessage(hCombo, CB_ADDSTRING, NULL, (LPARAM)"Channel exit");
SendMessage(hCombo, CB_SELECTSTRING, NULL, (LPARAM)"Log in");
SendMessage(hCombo, CB_SETMINVISIBLE, NULL, NULL);
hDo = CreateWindow("BUTTON", "Log in", WS_CHILD | WS_VISIBLE, 340, 55, 135, 20, hWnd,
(HMENU)DoBtn, hInstance, NULL);
hStatic = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE,"static", "", SS_CENTER |
SS_LEFT | SS_SUNKEN |
WS_BORDER | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE, 480, 30, 100, 45, hWnd,
(HMENU)Static, hInstance, NULL);
hTime = CreateWindowEx(WS_EX_STATICEDGE, DATETIMEPICK_CLASS, "Calendar",
DTS_LONGDATEFORMAT | WS_CHILD | WS_DLGFRAME |
WS_OVERLAPPED | WS_VISIBLE, 440, 360, 140, 50, hWnd, (HMENU)Time, hInstance,
NULL);
hStatic2 = CreateWindowEx(WS_EX_CLIENTEDGE | WS_EX_STATICEDGE,"static", "", SS_CENTER |
SS_LEFT | SS_SUNKEN |
WS_BORDER | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE, 350, 120, 230, 25, hWnd,
(HMENU)Static2, hInstance, NULL);
25
InitCommonControls();
hTree = CreateWindowEx(WS_EX_STATICEDGE, WC_TREEVIEW, "Channels", WS_VISIBLE | WS_CHILD |
TVS_HASLINES |
TVS_HASBUTTONS | TVS_LINESATROOT | WS_DLGFRAME | WS_VSCROLL | WS_HSCROLL,
350, 150, 230, 200, hWnd, (HMENU) TreeView, hInstance, NULL);
ret = RegisterHotKey(hWnd,0xB001, MOD_CONTROL | MOD_ALT, 'D');
SendMessage(hIp,WM_ACTIVATE, WA_ACTIVE, NULL);
ShowWindow(hStatic,SW_HIDE);
ShowWindow(hWnd,SW_SHOW);
UpdateWindow(hWnd);
while (GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
FILE *f;
PAINTSTRUCT ps;
HTREEITEM hRoot;
LPTV_ITEM item = new TV_ITEM;
int nLen, i;
char *string1 = new char [stringLength];
char *string2 = new char [stringLength];
switch (message) {
case WM_HOTKEY:
SendMessage(hLog, WM_SETTEXT, NULL, (LPARAM)"");
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
STS("exit");
hRoot=TreeView_GetChild(hTree,TVI_ROOT);
TransSwitch=1;
while(hRoot!=NULL){
SendMessage(hTree, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hRoot);
SendMessage(hTree, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hRoot);
hRoot=GetTreeItem(item, NULL);
sprintf(string1,"%s.chnl",item->pszText);
remove(string1);
hRoot=TreeView_GetNextVisible(hTree,hRoot);
}
PostQuitMessage(0);
break;
case WM_COMMAND:
switch(LOWORD(wParam)){
case ExitBtn:
SendMessage(hWnd, WM_DESTROY, NULL, NULL);
break;
case CnctBtn:
if (ShowWindow(hIp,NULL)){
GetWindowText(hIp,string1,16);
if (Connecting(string1, hWnd)){
ShowWindow(hIp,SW_SHOW);
MessageBox(hWnd,"Connection
error!","Error",MB_OK | MB_ICONERROR);
break;
}
SendMessage(hStatic2, WM_SETTEXT, NULL, (LPARAM)"ALL
is active");
SendMessage(hTree,WM_ACTIVATE, WA_ACTIVE, NULL);
26
SendMessage(hLog, WM_SETTEXT, NULL, (LPARAM)"");
SendMessage(hIp, WM_ACTIVATE, WA_ACTIVE, NULL);
MessageBox(hWnd,"You are successfully connected to a
server!","Information",MB_OK | MB_ICONINFORMATION);
SendMessage(hCnct, WM_SETTEXT, NULL, (LPARAM)"To
disconnect");
ShowWindow(hIp, SW_HIDE);
}
else{
STS("exit");
hRoot=TreeView_GetChild(hTree,TVI_ROOT);
TransSwitch=1;
while(hRoot!=NULL){
SendMessage(hTree, TVM_EXPAND, TVE_COLLAPSE,
(LPARAM)hRoot);
SendMessage(hTree, TVM_SELECTITEM,
TVGN_CARET, (LPARAM)hRoot);
hRoot=GetTreeItem(item, NULL);
sprintf(string1,"%s.chnl",item->pszText);
remove(string1);
hRoot=TreeView_GetNextVisible(hTree,hRoot);
}
TreeView_DeleteAllItems(hTree);
SendMessage(hCnct, WM_SETTEXT, NULL, (LPARAM)"To
connect");
SendMessage(hStatic2, WM_SETTEXT, NULL, (LPARAM)"");
SendMessage(hLog, WM_SETTEXT, NULL, (LPARAM)"");
ShowWindow(hIp, SW_SHOW);
ShowWindow(hNick,SW_SHOW);
ShowWindow(hPas1,SW_SHOW);
ShowWindow(hStatic,SW_HIDE);
SendMessage(hIp, WM_ACTIVATE, WA_ACTIVE, NULL);
}
break;
case SndBtn:
GetWindowText(hMsg, string1, 101);
GetTreeItem(item,NULL);
sprintf(string2,"msg %s %s %s",item->pszText,nick,string1);
STS(string2);
break;
case DoBtn:
switch (SendMessage(hCombo, CB_GETCURSEL, NULL ,NULL)){
case 0:
if (ShowWindow(hIp,SW_SHOW)){
MessageBox(hWnd,"You are not connected
to any server!","Error",MB_OK | MB_ICONERROR);
break;
}
ShowWindow(hIp, SW_HIDE);
GetWindowText(hNick, string1, 26);
sprintf(string2,"auth %s ",string1);
GetWindowText(hPas1, string1, 26);
strcat(string2,string1);
STS(string2);
Sleep(250);
switch(answer){
case 0:
MessageBox(hWnd,"You have
successfully entered!","Information",MB_OK | MB_ICONINFORMATION);
break;
case 2:
MessageBox(hWnd,"The incorrect
password!","Error",MB_OK | MB_ICONERROR);
break;
case 3:
MessageBox(hWnd,"Such user is
not registered!","Error",MB_OK | MB_ICONERROR);
break;
27
case 4:
MessageBox(hWnd,"You have
already entered!","Information",MB_OK | MB_ICONINFORMATION);
break;
}
sprintf(string2,"You are %s",nick);
SendMessage(hStatic,WM_SETTEXT,NULL,(LPARAM)string2);
if (answer!=0)
break;
ShowWindow(hNick,SW_HIDE);
ShowWindow(hPas1,SW_HIDE);
ShowWindow(hStatic,SW_SHOW);
SendMessage(hIp ,WM_ACTIVATE, WA_ACTIVE,
NULL);
break;
case 1:
if (ShowWindow(hIp,SW_SHOW)){
MessageBox(hWnd,"You are not connected
to any server!","Error",MB_OK | MB_ICONERROR);
break;
}
ShowWindow(hIp, SW_HIDE);
GetWindowText(hNick, string1, 26);
sprintf(string2,"reg %s ",string1);
GetWindowText(hPas1, string1, 26);
strcat(string2,string1);
STS(string2);
Sleep(250);
switch(answer){
case 0:
MessageBox(hWnd,"Successful
registration! Can enter!","Information",MB_OK | MB_ICONINFORMATION);
break;
case 1:
MessageBox(hWnd,"Such user is
already registered!","Error",MB_OK | MB_ICONERROR);
break;
}
sprintf(string2,"You are %s",nick);
SendMessage(hStatic,WM_SETTEXT,NULL,(LPARAM)string2);
if (answer!=0)
break;
ShowWindow(hNick,SW_HIDE);
ShowWindow(hPas1,SW_HIDE);
ShowWindow(hStatic,SW_SHOW);
SendMessage(hIp ,WM_ACTIVATE, WA_ACTIVE,
NULL);
break;
case 2:
if (ShowWindow(hNick,SW_SHOW)){
MessageBox(hWnd,"You are not
authorised!","Prevention",MB_OK | MB_ICONEXCLAMATION);
break;
}
ShowWindow(hNick, SW_HIDE);
hRoot=TreeView_GetChild(hTree,TVI_ROOT);
while(hRoot!=NULL){
SendMessage(hTree, TVM_EXPAND,
TVE_COLLAPSE, (LPARAM)hRoot);
SendMessage(hTree, TVM_SELECTITEM,
TVGN_CARET, (LPARAM)hRoot);
28
hRoot=GetTreeItem(item, NULL);
sprintf(string1,"quit %s ",item>pszText);
Sleep(250);
STS(string1);
hRoot=TreeView_GetNextVisible(hTree,hRoot);
}
TreeView_DeleteAllItems(hTree);
Sleep(250);
STS("logout");
Sleep(250);
STS("join ALL ");
ShowWindow(hNick,SW_SHOW);
ShowWindow(hPas1,SW_SHOW);
ShowWindow(hStatic,SW_HIDE);
SendMessage(hStatic ,WM_ACTIVATE, WA_ACTIVE,
NULL);
break;
case 3:
if (ShowWindow(hIp,SW_SHOW)){
MessageBox(hWnd,"You are not connected
to any server!","Error",MB_OK | MB_ICONERROR);
break;
}
ShowWindow(hIp, SW_HIDE);
GetWindowText(hChnl, string1, 26);
sprintf(string2,"join %s ",string1);
GetWindowText(hPas2, string1, 26);
strcat(string2,string1);
STS(string2);
Sleep(250);
if (answer==6)
MessageBox(hWnd,"It was not possible
to enter on the channel!","Error",MB_OK | MB_ICONERROR);
break;
case 4:
if (ShowWindow(hIp,SW_SHOW)){
MessageBox(hWnd,"You are not connected
to any server!","Error",MB_OK | MB_ICONERROR);
break;
}
ShowWindow(hIp, SW_HIDE);
GetWindowText(hChnl, string1, 26);
sprintf(string2,"creg %s ",string1);
GetWindowText(hPas2, string1, 26);
strcat(string2,string1);
STS(string2);
Sleep(250);
switch(answer){
case 0:
MessageBox(hWnd,"Successful
registration! Can enter!","Information",MB_OK | MB_ICONINFORMATION);
break;
case 7:
MessageBox(hWnd,"Such channel
is already registered!","Error",MB_OK | MB_ICONERROR);
break;
case 8:
MessageBox(hWnd,"You are not
registered user!","Error",MB_OK | MB_ICONERROR);
break;
}
SendMessage(hIp ,WM_ACTIVATE, WA_ACTIVE,
NULL);
break;
29
case 5:
hRoot=TreeView_GetSelection(hTree);
TransSwitch=1;
if (TreeView_GetParent(hTree,hRoot)!=NULL){
hRoot=TreeView_GetParent(hTree,hRoot);
SendMessage(hTree, TVM_SELECTITEM,
TVGN_CARET, (LPARAM)hRoot);
}
hRoot=GetTreeItem(item,NULL);
sprintf(string1,"quit %s ",item->pszText);
STS(string1);
sprintf(string1,"%s.chnl",item->pszText);
remove(string1);
SendMessage(hTree, TVM_DELETEITEM, NULL,
(LPARAM)hRoot);
SendMessage(hIp ,WM_ACTIVATE, WA_ACTIVE,
NULL);
break;
}
break;
}
switch(HIWORD(wParam)){
case CBN_SELCHANGE:
SendMessage(hCombo, CB_GETLBTEXT, SendMessage(hCombo,
CB_GETCURSEL, NULL, NULL), (LPARAM)string1);
SetWindowText(hDo,string1);
break;
case EN_SETFOCUS:
switch(LOWORD(wParam)){
case MsgEdit:
GetWindowText(hMsg, string1, 26);
if (!strcmp("Enter the message",string1))
SendMessage (hMsg, WM_SETTEXT, 0,
(LPARAM)"");
break;
case LoginEdit:
GetWindowText(hNick, string1, 26);
if (!strcmp("Nickname",string1))
SendMessage (hNick, WM_SETTEXT, 0,
(LPARAM)"");
break;
case PswdEdit:
GetWindowText(hPas1, string1, 26);
if (!strcmp("Password",string1))
SendMessage (hPas1, WM_SETTEXT, 0,
(LPARAM)"");
break;
case ChnEdit:
GetWindowText(hChnl, string1, 26);
if (!strcmp("Channel name",string1))
SendMessage (hChnl, WM_SETTEXT, 0,
(LPARAM)"");
break;
}
break;
case EN_KILLFOCUS:
switch(LOWORD(wParam)){
case MsgEdit:
if (!SendMessage(hMsg, EM_LINELENGTH,0,NULL))
SendMessage (hMsg, WM_SETTEXT, 0,
(LPARAM)"Enter the message");
break;
case LoginEdit:
30
if (!SendMessage(hNick,
EM_LINELENGTH,0,NULL))
SendMessage (hNick, WM_SETTEXT, 0,
(LPARAM)"Nickname");
break;
case PswdEdit:
if (!SendMessage(hPas1,
EM_LINELENGTH,0,NULL))
SendMessage (hPas1, WM_SETTEXT, 0,
(LPARAM)"Password");
break;
case ChnEdit:
if (!SendMessage(hChnl,
EM_LINELENGTH,0,NULL))
SendMessage (hChnl, WM_SETTEXT, 0,
(LPARAM)"Channel name");
break;
}
break;
}
break;
case WM_NOTIFY:
switch(((LPNMHDR)lParam)->code){
case TVN_SELCHANGED:
if (!TransSwitch){
hRoot=GetTreeItem(item,NULL);
if (TreeView_GetParent(hTree,hRoot)!=NULL)
break;
sprintf(string1,"%s is active",item->pszText);
SendMessage(hStatic2,WM_SETTEXT,NULL,(LPARAM)string1);
GetTreeItem(item, SELECT);
sprintf(log,"%s.chnl",item->pszText);
f=fopen(log,"w");
GetWindowText(hLog,string1,maxLog+1);
fprintf(f,"%s",string1);
fclose(f);
GetTreeItem(item, hRoot);
sprintf(log,"%s.chnl",item->pszText);
SELECT=hRoot;
SendMessage(hLog, WM_SETTEXT, NULL, (LPARAM)"");
f=fopen(log,"r");
if (f==NULL)
break;
fgets(string1,2,f);
if (feof(f))
break;
else
rewind(f);
while(!feof(f)){
fgets(string1,maxMsg,f);
if (feof(f))
break;
nLen = GetWindowTextLength (hLog);
SendMessage (hLog, EM_SETSEL, nLen, nLen);
SendMessage (hLog, EM_REPLACESEL, 0,
(LPARAM)string1);
}
fclose(f);
}
break;
}
break;
default:
delete item;
delete[] string1;
delete[] string2;
return DefWindowProc(hWnd, message, wParam, lParam);
31
}
delete item;
delete[] string1;
delete[] string2;
}
32
Download