
- •Разработка сетевых приложений
- •План
- •Сокеты (socket)
- •Поддержка всех типов протоколов
- •Домены сокетов
- •Семейства протоколов
- •Примеры семейств протоколов /usr/include/linux/socket.h
- •Типы сокетов домена Интернет
- •Функция socket()
- •Привязка сокета к сетевому адресу и порту
- •Функция bind()
- •Формат адреса для семейства протоколов Интернет
- •Порядок байт сети и локальной машины
- •Пример привязки адреса
- •Возможности получения адресов
- •Использование службы доменных имен
- •Режимы сокетов
- •Соединение сокетов
- •Функция connect()
- •Серверный сокет в режиме прослушивания (LISTEN)
- •Сокет в режиме приема входящих соединений (accept)
- •Прием и передача информации
- •Диаграмма работы с
- •Класс sock_1
- •Пример сервера
- •Пример клиента
- •Пример выполнения
- •Синхронное и асинхронное выполнение
- •Проверка наличия данных
- •Удаленные вызовы процедур
- •Extended data representation
- •Использование компилятора RPCGEN
- •Пример описания интерфейсов
- •Создание тела процедуры
- •Создание клиента
- •Компиляция клиента и сервера
- •Пример работы
- •CORBA
- •Процесс создания распределенной программы
- •Пример – описание интерфейса
- •Создание тела функции (test- skelimpl.c)
- •Создание сервера
- •Пример сервера (test- skelimpl.c)
- •Создание клиента (test_client.c)
- •Пример клиента
- •Компиляция сервера и клиента
- •Запуск клиента и сервера
- •Вопросы

Сокет в режиме приема входящих соединений (accept)
Если есть входящие соединения, то серверный сокет должен их принять
После приема возвращается новый сокет, соединенный с клиентским
Серверный сокет продолжает слушать
Фунция accept()
int new_sock = accept(int s, struct sockaddr *addr, socklen_t *addrlen);
s – сокет, на которое поступило соединение
addr – адрес и протокол партнера по соединению addrlen – длина адреса

Прием и передача информации
Через два соединенных сокета возможен прием и передача данных в обоих направлениях
Прием – функция read() или recv()
ssize_t read(int fd, void *buf, size_t count); fd – дескриптор сокета
buf – указатель начала данных в памяти count – количество байт данных для передачи
Передача данных – write() recv()
ssize_t write(int fd, const void *buf, size_t count); fd – дескриптор сокета
buf – указатель начала области памяти, куда писать данные count – количество байт данных для приема

Диаграмма работы с
сокетами TCP |
Клиент |
||||
|
Сервер |
||||
|
socket() |
|
|
|
|
|
|
socket() |
|||
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bind() |
|
connect() |
|
|
|
listen() возвращаем
соединенный сокет accept()
возвращаем соединенный сокет
read() write() Send() recv()
read() write() Send() recv()

Класс sock_1
Разработан для упрощения работы с сокетами
Имеет функции с тем же названием, но более простые в использовании

Пример сервера
#include "sock_1.h" #include <iostream> using namespace std; int main(){
sock_1 sock_listen(PF_INET, SOCK_STREAM); try {
if(sock_listen.bind(NULL,34567)<0) throw "bind error"; int fd;
if((fd = sock_listen.accept(NULL,NULL)) < 0 ) throw "accept error"; sock_1 sock_connected(fd);
char message[4096];
int len = sock_connected.read(message,4096);
cout << "CLIENT SENT "<<message<<" of length "<<len<<endl; sock_connected.write(message,len);
} catch(char * er){ |
|
|
cerr <<er ; |
perror(""); |
cerr <<endl; |
return -1; |
|
|
} |
|
|
return 0; |
|
|
} |
|
|
|
|
|

Пример клиента
#include "sock_1.h" #include <iostream> using namespace std; int main(){
sock_1 connect_sock(PF_INET,SOCK_STREAM); try {
if(connect_sock.connect("cluster.univ.kiev.ua",34567)<0) throw "connect";
char message[4096]="HI server"; connect_sock.write(message,strlen(message)); int len = connect_sock.read(message,4096);
cerr << "server send " << message <<"of length "<<len<<endl; }catch (char* er) {
cerr <<er ; perror(NULL); cerr <<endl; return -1;
}
return 0;
}

Пример выполнения
[saa@cluster socket]$ g++ ./client.cpp ./sock_1.cpp -o client [saa@cluster socket]$ ./client
server send HI serverof length 9
[saa@cluster socket]$ g++ ./server.cpp ./sock_1.cpp -o server [saa@cluster socket]$ ./server
CLIENT SENT HI server of length 9

Синхронное и асинхронное выполнение
Функции работы с сокетами могут блокироваться
connect()
accept()
read()
write()
Процесс останавливается в ожидании события
Для предотвращения ожидания возможны следующие варианты
Проверка наличия данных в сокете
Неблокирующий режим
Асинхронный ввод-вывод

Проверка наличия данных
Функция select()
int select(int n, |
fd_set *readfds, |
|
fd_set *writefds, |
|
fd_set *exceptfds, |
|
struct timeval *timeout); |
Проверка возможности ввода-вывода для дескрипторов, указанных в аргументах
|
readfds - |
на возможность чтения или успешность |
accept |
|
writefds - на возможность записи или успешность |
connect |
|
|
Exceptfds |
- на наличие ошибок |
|
N - максимальный номер дескриптора
Timeout – максимальное время ожидания

Удаленные вызовы процедур
Надстройка над сокетами
Позволяют просто
передавать сложные структуры данных на удаленную машину
Выполнять с ними действия
Возвращать результат
Это выглядит как вызов процедуры на удаленной машине