Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Судаков / Лекции / lec21_net.ppt
Скачиваний:
27
Добавлен:
20.03.2015
Размер:
103.42 Кб
Скачать

Сокет в режиме приема входящих соединений (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 – максимальное время ожидания

Удаленные вызовы процедур

Надстройка над сокетами

Позволяют просто

передавать сложные структуры данных на удаленную машину

Выполнять с ними действия

Возвращать результат

Это выглядит как вызов процедуры на удаленной машине

Соседние файлы в папке Лекции