
- •2. Функции для работы с сокетами
- •3. Схема работы сервера и клиента с предварительным установлением связи
- •4. Пример сервера и клиента
- •5. Цели и задачи
- •6. Порядок выполнения лабораторной работы
- •7. Варианты заданий (1-15)
- •8. Варианты заданий (16-30)
- •9. Варианты заданий (31-45)
- •10. Варианты заданий (46-60)
3. Схема работы сервера и клиента с предварительным установлением связи
Сервер |
Клиент |
Создать сокет1 ; Связать сокет1 с адресом ; Уведомить систему о готовности принимать запросы на установление связи ; while (1) { Извлечь запрос из очереди запросов на установление связи и получить новый сокет2 для обмена информацией с клиентом, пославшим запрос ; Породить дочерний процесс для взаимодействия через сокет2 с клиентом, пославшим запрос ; } |
Создать сокет :
Послать запрос на установление предварительного соединения ;
Осуществлять коммуникации с сервером ; |
4. Пример сервера и клиента
Приложение клиент устанавливает соединение с сервером, посылает ему сообщение, получает ответ от сервера и выводит его на экран.
Программный код клиента.
#include <stdio.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 1125
int main()
{ int sd,num ; //sd – дескриптор сокета
char buf[60] ; //для посылки и получения данных
sprintf(buf,"Привет!") ;
struct sockaddr_in saddr ; //адрес сервера
bzero(&saddr, sizeof(saddr)) ; //очистить адрес
saddr.sin_family=AF_INET ;
saddr.sin_port = PORT ;
saddr.sin_addr.s_addr=INADDR_ANY ;//клиент и сервер выполняются на одной машине
sd=socket(AF_INET, SOCK_STREAM, 0) ;
if (sd<0) { fprintf(stdout, "\nНевозможно создать сокет") ; return 0 ; }
if ( connect(sd, (struct sockaddr *)&saddr, sizeof(saddr))<0 )
{ fprintf(stdout,"\nНевозможно установить соединение с сервером") ; return 0 ;}
num = send(sd,buf,sizeof(buf),0) ; //послать сообщение серверу
if (num<0) { fprintf(stdout,"\nОшибка") ; return 0 ;}
num=recv(sd,buf,60,0) ; //получить ответ от сервера
if (num<0) { fprintf(stdout,"\nОшибка") ; return 0 ; }
else fprintf(stdout,"\nПолучен ответ %s",buf) ;
return 1 ;
}
Приложение сервер извлекает запросы на установление соединения, и для последующего обслуживания каждого запроса создает процесс, в котором получает информацию от определенного клиента и отсылает ее ему же. Заметим, что конкретно для этой задачи создание дополнительного процесса является излишним, но когда взаимодействие сервера и клиентов более сложное, правильной будет именно такая схема.
Программный код сервера.
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 1125
int main()
{ int sd,ns ; //sd – дескриптор сокета
//saddr – адрес сервера, caddr – для записи адресов клиентов
struct sockaddr_in saddr, caddr ;
char buf[60] ; //для посылки и получения данных
sd=socket(AF_INET,SOCK_STREAM,0) ;
if (sd<0) { fprintf(stdout,"\nНевозможно создать сокет ") ; return 0 ;}
else fprintf(stdout,"\nСокет создан ") ;
bzero(&saddr, sizeof(saddr)) ; //очистить адрес
saddr.sin_family = AF_INET ;
saddr.sin_addr.s_addr = INADDR_ANY ;
saddr.sin_port=PORT ;
if ( bind(sd, (struct sockaddr *)&saddr, sizeof(saddr))<0 )
{ fprintf(stdout,"\nНевозможно связать сокет с адресом") ; return 0 ;}
if ( listen(sd,3)<0 )
{ fprintf(stdout,"\nОшибка вызова listen() ") ; return 0 ; }
else fprintf(stdout,"\nСервер запущен") ;
while(1)
{ bzero(&caddr,sizeof(caddr)) ; //очистить адрес
int sd2,pid ; // sd2 – дескриптор сокета для коммуникации с клиентом
socklen_t addrlen ; //для получения размера адреса клиента
sd2=accept(sd, (struct sockaddr *)&caddr, &addrlen) ;
if (sd2>0) { fprintf(stdout,"\nПринят запрос на установление связи ") ;
pid=fork() ;
if (pid<0) { fprintf(stdout,"\nНевозможно создать процесс") ; continue ; }
if (pid==0) //дочерний процесс осуществляет коммуникации с клиентом
{ int num ;
close(sd) ; //дочернему процессу не нужен дескриптор sd
num=recv(sd2,buf,60,0) ;
if (num<0) { fprintf(stdout,"\nОшибка чтения ") ; return 0 ; }
char buf2[60] ;
sprintf(buf2,"Ответ сервера %s",buf) ;
num=send(sd2,buf2,sizeof(buf2),0) ;
if (num<0) { fprintf(stdout,"\nОшибка записи ") ; return 0 ; }
return 1 ;
}
close(sd2) ; } ; //родительскому процессу не нужен дескриптор sd2
}
return 1 ;
}