Часть 1 – программирование (5 задач, из лаб. работ 1-4, 8 по своему варианту): Задача №1 (л.р.1 вариант №2): Осуществить взаимодействие клиента и сервера на основе протокола TCP/IP. Функционирование клиента и сервера реализовать следующим образом: клиент посылает слово серверу, сервер возвращает назад в обратном порядке следования букв это слово клиенту. Задача №2 (л.р.2 вариант №2): Осуществить взаимодействие клиента и сервера на основе протокола UDP. Функционирование клиента и сервера реализовать следующим образом: клиент посылает серверу дату в формате ДД.ММ.ГГ, сервер определяет существует ли она и возвращает "истина", если дата корректна, в противном случае - "ложь". Задача №3 (л.р.3 вариант №2): Осуществить взаимодействие клиента и сервера на основе протокола TCP/IP. Реализовать параллельное соединение с использованием многопоточности. Функциональные возможности клиента реализовать следующим образом: клиент вводит с клавиатуры строку символов и посылает ее серверу. Признак окончания ввода строки - нажатие клавиши "Ввод". Функциональные возможности сервера реализовать следующим образом: сервер, получив эту строку, должен определить длину введенной строки, и, если эта длина четная, то удаляются 3 первых и 2 последних символа. Результаты преобразований этой строки возвращаются назад клиенту. Задача №4 (л.р.4 вариант №2): Осуществить взаимодействие клиента и сервера без установления логического соединения (UDP). Реализовать параллельное соединение с использованием многопоточности. Вводится текст. Вывести строки, содержащие двузначные числа. Задача №5 (л.р.8 вариант №7): В протоколе отправки SMS-сообщений ограничить частоту отправки сообщений с одного IP адреса по времени. Добавить команду sms (без параметров), которая выводила б правила пользования услугой.
Часть 2 контрольной работы: 1. Физический и канальный уровень – функциональное назначение. 2. LLC и его виды 3. Структура кадра LLC 4. Метод доступа CSMA/CD 5. Понятие коллизии причины ее возникновения 6. Требования к физической среде Ethernet 7. Interframe gap, jam-последовательность, slot time, collision window – назначение и расчет 8. Почему окно коллизий равно времени двукратного прохождения сигнала между самыми удаленными узлами сети 9. Пример расчета максимальной пропускной способности сегмента Ethernet. 10. Формат MAC-кадра и времена его передачи для Ethernet и Fast Ethernet. 11. Форматы кадров Ethernet 12. По каким критериям производиться расчет сети Ethernet. 13. Почему расчет задержки распространения необходимо в общем случае производить дважды. 14. Почему минимальным временем распространения кадра в 10BASE-T принято 575 бит. 15. Почему уменьшение межкадрового расстояния повышает вероятность потери кадров. 16. Почему происходит рассинхронизация кадров при прохождении повторителей. Задача (Вариант №11): привести схему сети и предложения по изменению условий в случае невыполнимости базовой задачи. Вариант 1 сегмент 2 сегмент 3 сегмент 4 сегмент 5 сегмент 6 сегмент 11 10Base-T 10Base-T 10Base-T 10Base-2 10Base-T 10Base-2 Брать максимальную длину сегмента. По результатам расчетов дать заключение о работоспособности сети.
Задача №1 (л.р.1 вариант №2) Осуществить взаимодействие клиента и сервера на основе протокола TCP/IP. Функционирование клиента и сервера реализовать следующим образом: клиент посылает слово серверу, сервер возвращает назад в обратном порядке следования букв это слово клиенту. Краткое описание алгоритма: Сервер:
int main() { WORD wVersionRequested; //определяет макс. номер версии WinSock, доступный приложению WSADATA wsaData; //структура wsaData, содержит номер версии (поле wVersion), //максимальный номер версии (поле wHighVersion), //текстовые строки с описанием реализации WinSock, максимальное число сокетов, //доступных процессу и максимально допустимый размер дейтаграмм wVersionRequested=MAKEWORD(2,2); WSAStartup(wVersionRequested,&wsaData); //инициализация WinSock API SOCKET s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //дескриптор сокета, функция для // создания сокета, принимает три параметра: домен, тип сокета и протокол struct sockaddr_in local; //структура адреса local.sin_family=AF_INET; //всегда имеет значение AF_INET local.sin_port=htons(1280); //определяет порт, который будет ассоциирован с сокетом local.sin_addr.s_addr=htonl(INADDR_ANY); //физический IP-адрес компьютера int c=bind(s,(struct sockaddr*)&local,sizeof(local)); //для связывания конкретного адреса с сокетом int r=listen(s,5); //помещает сокет в состояние прослушивания while (true) { char b[255]; sockaddr_in remote_addr; int size=sizeof(remote_addr); SOCKET s2=accept(s,(struct sockaddr*)&remote_addr,&size);//При получении запроса клиента //выполняется открытие соединения while (recv(s2,b,sizeof(b),0)!=0) //прием данных через сокет потока { strrev(b); //инвертировать строку send(s2,b,sizeof(b),0);// посылает данные на соединенный сокет } closesocket(s2); //завершение работы сокета } WSACleanup(); //завершая программу, прекращаем работу с WinSock return 0; } Клиентская часть: #include <winsock2.h> #include <iostream.h> #include <stdlib.h>
int main() { WORD wVersionRequested; WSADATA wsaData; wVersionRequested=MAKEWORD(2,2); WSAStartup(wVersionRequested,&wsaData); struct sockaddr_in peer; peer.sin_family=AF_INET; peer.sin_port=htons(1280); peer.sin_addr.s_addr=inet_addr("127.0.0.1");// т.к. клиент и сервер на одном компьютере, //пишем адрес 127.0.0.1 SOCKET s=socket(AF_INET,SOCK_STREAM,0); connect(s,(struct sockaddr*) &peer,sizeof(peer));//приложение-клиент посылает запрос //на открытие соединения char buf[255],b[255]; cout<<"Enter one word, please"<<endl<<endl; cin.getline(buf,100,'\n'); send(s,buf,sizeof(buf),0); if (recv(s,b,sizeof(b),0)!=0) { b[strlen(b)]='\0'; //Удаление ненужных символов в конце строки cout<<b<<endl<<endl; } closesocket(s); WSACleanup(); return 0; }
Результаты тестирования:
Задача №2 (л.р.2 вариант №2) Осуществить взаимодействие клиента и сервера на основе протокола UDP. Функционирование клиента и сервера реализовать следующим образом: клиент посылает серверу дату в формате ДД.ММ.ГГ, сервер определяет существует ли она и возвращает "истина", если дата корректна, в противном случае - "ложь". Краткое описание алгоритма: Сервер:
void main(void) { WORD wVersionRequested; //определяет макс. номер версии WinSock, доступный приложению WSADATA wsaData; wVersionRequested=MAKEWORD(2,2); int err = WSAStartup(wVersionRequested,&wsaData); //инициализация WinSock API SOCKET s; s = socket(AF_INET,SOCK_DGRAM,0); // Вызов функции socket( ), //тип создаваемого сокета SOCK_DGRAM struct sockaddr_in ad; //структура адреса ad.sin_port = htons(1024); //определяет порт, который будет ассоциирован с сокетом ad.sin_family = AF_INET; //всегда имеет значение AF_INET ad.sin_addr.s_addr = 0; //подставляет подходящий iр bind(s,(struct sockaddr*) &ad,sizeof(ad)); char b[50],str[10]; char cDD[5], cMM[5], cYY[5]; int l = sizeof(ad); int rv = recvfrom(s, b, strlen(b), 0, (struct sockaddr*) &ad, &l); //приём данных от приложения-клиента b[rv]='\0'; int flag=0; char *p1, *p2; p1=p2=b; for (unsigned i=0;i<=strlen(b);i++) { p2++; if(b[i]=='.'||b[i]=='\0') { int len=int(p2-p1); switch (flag) { case 0: strncpy(cDD,p1,len); cDD[len]='\0'; flag=1; break; case 1: strncpy(cMM,p1,len); cMM[len]='\0'; flag=2; break; case 2: strncpy(cYY,p1,len); cYY[len]='\0'; break; } p1=p2; } } if(atoi(cDD)<=30 && atoi(cMM)<=12 && atoi(cYY)<=2009) strcpy(str,"true"); else strcpy(str,"false"); sendto(s, str, lstrlen(str), 0, (struct sockaddr*) &ad, l); //отправка данных closesocket(s); //завершение работы сокета WSACleanup(); //завершая программу, прекращаем работу с WinSock } Клиентская часть: #include <winsock2.h> #include <stdio.h> #include <string.h> #include <windows.h> #include <iostream.h>
int main(void) { char buf[50], b[10]; WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2,2); int err=WSAStartup(wVersionRequested, &wsaData); if(err != 0) return 0; SOCKET s = socket(AF_INET,SOCK_DGRAM,0); struct sockaddr_in add; add.sin_family = AF_INET; add.sin_port = htons(1024); add.sin_addr.s_addr = inet_addr("127.0.0.1"); //явное указание IP-адреса //при помощи строкового представления int t = sizeof(add); cout<<"Enter date in a format DD.MM.YY, please"<<endl; cin.getline(buf,100,'\n'); sendto(s, buf, lstrlen(buf), 0, (struct sockaddr*) &add, t); int rv = recvfrom(s, b, lstrlen(b), 0, (struct sockaddr*) &add, &t); b[rv] = '\0'; cout<<b<<endl; closesocket(s); WSACleanup(); return 0; } Результаты тестирования:
Задача №3 (л.р.3 вариант №2) Осуществить взаимодействие клиента и сервера на основе протокола TCP/IP. Реализовать параллельное соединение с использованием многопоточности. Функциональные возможности клиента реализовать следующим образом: клиент вводит с клавиатуры строку символов и посылает ее серверу. Признак окончания ввода строки - нажатие клавиши "Ввод". Функциональные возможности сервера реализовать следующим образом: сервер, получив эту строку, должен определить длину введенной строки, и, если эта длина четная, то удаляются 3 первых и 2 последних символа. Результаты преобразований этой строки возвращаются назад клиенту. Краткое описание алгоритма: Сервер:
WINBASEAPI HANDLE WINAPI CreateThread //создает поток, который выполняться в пределах //адресного пространства вызова процесса (LPSECURITY_ATTRIBUTES lpThreadAttributes, // указатель на атрибуты безопасности DWORD dwStackSize, // размер стека начального потока LPTHREAD_START_ROUTINE lpStartAddress, // указатель на функцию потока, для выполнения ее // потоком и представления начального адреса потока LPVOID lpParameter, // аргумент для нового потока DWORD dwCreationFlags, // создание флагов, eсли это нулевая величина, //то поток выполняется немедленно после его создания LPDWORD lpThreadId); // указатель на ID потокa для его получения
void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) return; SOCKET s=socket(AF_INET,SOCK_STREAM,0); sockaddr_in local_addr; local_addr.sin_family=AF_INET; local_addr.sin_port=htons(1280); local_addr.sin_addr.s_addr=0; bind(s,(sockaddr *) &local_addr,sizeof(local_addr)); int c=listen(s,5); cout<<"Server receive ready"<<endl; cout<<endl; // извлекаем сообщение из очереди SOCKET client_socket; // сокет для клиента sockaddr_in client_addr; // адрес клиента(заполняется системой) int client_addr_size=sizeof(client_addr); // цикл извлечения запросов на подключение из очереди while((client_socket=accept(s,(sockaddr *)&client_addr, &client_addr_size))) { numcl++; print(); // Вызов нового потока для обслуживания клиента CreateThread(NULL,NULL,ThreadFunc,&client_socket,NULL, NULL); } WINBASEAPI VOID WINAPI ExitThread( DWORD dwExitCode ); } Клиентская часть: #include<stdio.h> #include<iostream.h> #include<winsock2.h>
void main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err=WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) return; while (true) { SOCKET s=socket(AF_INET,SOCK_STREAM,0); // указание адреса и порта сервера sockaddr_in dest_addr; dest_addr.sin_family=AF_INET; dest_addr.sin_port=htons(1280); dest_addr.sin_addr.s_addr=inet_addr("127.0.0.1"); connect(s,(sockaddr *)&dest_addr,sizeof(dest_addr)); char buf[100]; cout<<"Enter the string:"<<endl; fgets(buf,sizeof(buf),stdin); send(s,buf,100,0); if (recv(s,buf,sizeof(buf),0)!=0) cout<<"Result:"<<endl<<buf<<endl<<endl; closesocket(s); } WSACleanup(); }
Результаты тестирования:
Задача №4 (л.р.4 вариант №2) Осуществить взаимодействие клиента и сервера без установления логического соединения (UDP). Реализовать параллельное соединение с использованием многопоточности. Вводится текст. Вывести предложения, содержащие двузначные числа. Краткое описание алгоритма: Сервер:
void StringAnalizing(void* s) { char b[200]; sockaddr_in ad; ad.sin_family = AF_INET; ad.sin_port = htons(1280); //определяет порт ad.sin_addr.s_addr = htonl(INADDR_ANY); int j=sizeof(ad); int c=bind((SOCKET)s,(LPSOCKADDR)&ad, j); if (recvfrom((SOCKET)s,b,sizeof(b),0,(LPSOCKADDR) &ad, &j)!=0) { //приём данных от приложения-клиента cout<<b<<endl; char word[100], text[255]; strcpy(text,""); char *p1, *p2; p1=p2=b; for (int j=1;j<=strlen(b);j++) { p2++; if(b[j]=='.'||b[j]=='\0') { p2++; int len=int(p2-p1); strncpy(word,p1,len); word[len]='\0'; p1=p2; p2--; int flag=0; for (int i=0;i<strlen(word);i++) { if ((int)word[i]%256>=48&&(int)word[i]%256<=57) { i++; if ((int)word[i]%256>=48&&(int)word[i]%256<=57) { i++; if((int)word[i]%256<48||(int)word[i]%256>57) { flag++; if(flag==1) { strcat(text,word); strcat(text," "); } } else while((int)word[i]%256>=48 &&(int)word[i]%256<=57) i++; } } } } } //отправка данных sendto((SOCKET)s,text,sizeof(text),0,(LPSOCKADDR) &ad, j); } }
int main() { WORD wVersionRequested; //определяет макс. номер версии WinSock, доступный приложению WSADATA wsaData; wVersionRequested = MAKEWORD(2,2); int err = WSAStartup(wVersionRequested, &wsaData); //инициализация WinSock API if(err != 0) return -1; SOCKET s = socket(AF_INET, SOCK_DGRAM,0); // Вызов функции socket( ), //тип создаваемого сокета SOCK_DGRAM while(true) { _beginthread(StringAnalizing,0,(void*)s); //позволяет создавать поток } closesocket(s); //завершение работы сокета WSACleanup(); //завершая программу, прекращаем работу с WinSock return 0; } Клиентская часть: #include <winsock2.h> #include <iostream.h>
int main() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2,2); err = WSAStartup(wVersionRequested, &wsaData); struct sockaddr_in peer; peer.sin_family=AF_INET; peer.sin_port=htons(1280); peer.sin_addr.s_addr=inet_addr("127.0.0.1"); SOCKET s=socket(AF_INET,SOCK_DGRAM,0); int t=sizeof(peer); char buf[255],b[255]; cout<<"Enter the text, please"<<endl; cin.getline(buf,255,'\n'); sendto(s, buf, sizeof(buf), 0, (LPSOCKADDR)&peer, t); if (recvfrom(s,b,sizeof(b),0,(LPSOCKADDR)&peer,&t)!=0) cout<<endl<<"Result:"<<endl<<b<<endl; closesocket(s); WSACleanup(); return 0; } Результаты тестирования:
Задача №5 (л.р.8 вариант №7) В протоколе отправки SMS-сообщений ограничить частоту отправки сообщений с одного IP адреса по времени. Добавить команду sms (без параметров), которая выводила б правила пользования услугой. Файловая структура данных будет играть роль SMS-центра. Для представления файла удобно использовать класс CFile из библиотеки классов MFC. Для управления временем используем тип данных clock_t и функцию clock( ) для запуска и остановки таймера. Ограничение частоты отправки сообщений с одного IP адреса по времени: пользователь услуги имеет право отправить на центр сообщение, если прошло более 1 минуты с времени отправления предыдущего сообщения (не более 1 sms в минуту). Краткое описание алгоритма: Сервер:
Клиент:
Листинг: Серверная часть:
#include <iostream.h> #include "afx.h" //для использования класса CFile из библиотеки классов MFC #include <winsock2.h> //реализует программный интерфейс WinSock #include <process.h> // _beginthread, _endthread #include <string.h> #include <time.h> //функция clock( )
CFile f; //роль SMS-центра играет файловая структура данных CFileException ex;
void del(char* p) // удалить сообщение с номером { char tel[200]; int j=0; for (int i=0;p[i]!=' ';i++) { tel[j]=p[i]; j++; } tel[j]='\0'; char fName[200]; fName[0]='\0'; strcat(fName,tel); DeleteFile((LPCSTR)fName); cout<<"SMS is removed"<<endl; }
char * sms() //вывод правил пользования услугой { char *str; str="For sending the message enter:sms <a telephone number> <the message>\nFor removal of the message enter:del <a telephone number>\nFor an exit from the program enter:quit\nSending of the following message from one IP address not earlier than 1 minute"; cout<<str<<endl; return str; }
void sms(char* p,int n) //Отослать сообщение на SMS-центр для номера { char tel[200]; char str[200]; int j=0; for (int i=n;p[i]!=' ';i++) { tel[j]=p[i]; j++; } tel[j]='\0'; n=j+1; j=0; for(i=n;p[i];i++) { str[j]=p[i]; j++; } str[j]='\0'; char fName[200]; fName[0]='\0'; strcat(fName,tel); cout<<"sms processing..."; if (!f.Open(fName,CFile::modeWrite | CFile::modeCreate,&ex)) { cerr<<"SMS storage error. Try again\n"; exit(EXIT_FAILURE); } f.Write(str,strlen(str)); cout<<"sent successfully"<<endl; }
void SMSworking(void* newS) { clock_t start, finish, start1, finish1; //для управления временем используем тип данных clock_t int flag=0; int c; char p[200], com[200]; com[0]='\0'; p[0]='\0'; strcat(p,"SMS center connected...\n"); send((SOCKET)newS,p,sizeof(p),0); //отправка данных клиенту while((c=recv((SOCKET)newS,p,sizeof(p),0)!=0)) //приём дынных от клиента { int i=0; while (p[i]!=' ') { com[i]=p[i]; i++; }; com[i]='\0'; i++; if ((!strcmp(com,"sms"))&&strlen(p)>3) { if(flag==0) { start=clock(); start1 = clock(); sms(p,i); com[0]='\0'; flag=1; } else { finish1=clock(); // если с отправки сообщения прошло меньше минуты if((double)(finish1 - start1) / CLOCKS_PER_SEC < 60 ) cout<<"Cannot be sent"<<endl; else { start=clock(); start1=clock(); sms(p,i); com[0]='\0'; } } } if (!strcmp(com,"del")) { finish = clock(); // если с отправки сообщения прошло больше минуты if((double)(finish - start) / CLOCKS_PER_SEC > 60 ) cout<<"Cannot be canceled"<<endl; else del(p); com[0]='\0'; } if ((!strcmp(com,"sms"))&&strlen(p)==3) { char *a=sms(); char s[255]; strcpy(s,a); send((SOCKET)newS,s,sizeof(s),0); //отправка данных клиенту com[0]='\0'; } if (!strcmp(com,"quit")) { closesocket((SOCKET)newS); //завершение работы сокета //exit(EXIT_SUCCESS); com[0]='\0'; } } }
int main() { WORD wVersionRequested; //определяет макс.номер версии WinSock, доступный приложению WSADATA wsaData; //структура wsaData wVersionRequested = MAKEWORD(2,2); int err = WSAStartup(wVersionRequested, &wsaData); //инициализация WinSock API if(err != 0) return -1; sockaddr_in local; local.sin_family = AF_INET; local.sin_port = htons(1280); //определяет порт, который будет ассоциирован с сокетом local.sin_addr.s_addr = htonl(INADDR_ANY); //физический IP-адрес компьютера SOCKET s = socket(AF_INET, SOCK_STREAM,0); //создание сокета int c=bind(s,(struct sockaddr*)&local,sizeof(local)); //для связывания конкретного адреса с сокетом int r=listen(s,5); //помещает сокет в состояние прослушивания while(true) { sockaddr_in remote; int j = sizeof(remote); SOCKET newS = accept(s, (struct sockaddr*) &remote, &j); //При получении запроса клиента //выполняется открытие соединения _beginthread(SMSworking,0,(void*)newS); //позволяет создавать поток } WSACleanup(); return 0; } Клиентская часть: #include <winsock2.h> //реализует программный интерфейс WinSock #include <iostream.h>
int main() { WORD wVersionRequested; //определяет макс.номер версии WinSock, доступный приложению WSADATA wsaData; //структура wsaData wVersionRequested = MAKEWORD(2,2); int err = WSAStartup(wVersionRequested, &wsaData); //инициализация WinSock API if(err != 0) return -1; struct sockaddr_in peer; peer.sin_family=AF_INET; peer.sin_port=htons(1280); //определяет порт, который будет ассоциирован с сокетом peer.sin_addr.s_addr=inet_addr("127.0.0.1"); //физический IP-адрес компьютера SOCKET s=socket(AF_INET,SOCK_STREAM,0); //создание сокета connect(s,(struct sockaddr*) &peer,sizeof(peer)); char b[200],p[255]; recv(s,b,sizeof(b),0); //приём дынных с сервера cout<<b; b[0]='\0'; while (strcmp(b,"quit")) { cin.getline(b,200,'\n'); send(s,b,sizeof(b),0); //отправка команды на сервер
if(!strcmp(b,"sms")) { recv(s,p,sizeof(p),0); //приём дынных с сервера cout<<p<<endl; } } WSACleanup(); //завершая программу, прекращаем работу с WinSock return 0; }
Результаты тестирования: Сначала запустим серверную часть, потом клиентскую. Если соединение произойдет успешно, появится строка "SMS center connected...". Для отправки сообщения необходимо набрать: sms <номер телефона designtimesp=13502> <сообщение designtimesp=13503> Для удаления сообщения необходимо набрать: del <номер телефона designtimesp=13507> Для выхода из программы наберите quit Для вызова справки наберите sms. Отправка первого сообщения:
sms на номер 345 отправлено через 1 минуту, а на номер 765439 менее чем через 60сек.
sms без параметров – вызов правил пользования услугой.
Для отправки сообщения необходимо набрать: sms <номер телефона designtimesp=13502> <сообщение designtimesp=13503> Для удаления сообщения необходимо набрать: del <номер телефона designtimesp=13507> Для выхода из программы наберите quit Для вызова справки наберите sms.
1. Основы сетей передачи данных. В.Г. Олифер, Н.А. Олифер / Москва, 2005. – 176с. 2. Компьютерные сети: принципы, технологии, протоколы. В.Г. Олифер, Н.А. Олифер. 3. Лабораторные работы по КС.