Сокеты это средство связи между процессами, которые могут находиться как на разных компьютерах, так и на одном.
В этой статье я разберу две простых программы. Клиент и сервер. Для работы с сокетами нам необходимо подключить модуль Sockets. Что нам нужно для того чтобы написать программу клиент? Для этого необходимы следующие функции:
fpsocket - создание сокета
fpconnect - его привязка к адресу и порту, установка соединения
fpsend - посылка запроса
fprecv - прием ответа
CloseSocket - закрытие сокета
И так для начала нам надо создать сокет.
function fpsocket(domain:cint; xtype:cint; protocol:cint):cint;
Параметр domain определяет семейство протоколов, которое будет использоваться для взаимодействия. (Список возможных значений можно посмотреть в документации по Free Pascal. Файл rtl.pdf модуль Sockets). Для указания протокола IP следует использовать значение AF_INET. Второй параметр определяет тип сокета, т.е будет ли передаваться информация дейтаграммами с гарантией или без гарантии доставки, с установкой логического соединения, или еще как-нибудь. В рамках семейства IP протоколов реализованы передача дейтаграмм без гарантии доставки (протокол UDP) и надежная передача информации с установкой логического соединения (протокол TCP). Именно его мы и будем использовать. Для этого в качестве type укажем константу SOCK_STREAM. Для первого варианта существует константа SOCK_DGRAM. Третий параметр необязателен если первый имеет значение AF_INET, и мы будем использовать значение 0. В случае успешного завершения возвращается неотрицательное число - дескриптор сокета, в случае неудачи возвращается -1.
Для определения сокета нам понадобиться переменная типа TSocket
Следующая функция
function fpconnect(s: cint; name:psockaddr; namelen:TSockLen) : cint
s - дескриптор сокета, который мы получим при вызове функции fpsocket name - указатель на запись sockaddr, содержащую информацию о сокете. namelen - размер этой записи. В случае успеха connect возвращает 0, а в случае неудачи -1. Поля которые нам необходимо заполнить в переменной типа sockaddr:
1)sa_family
2)sin_addr
3)sin_port
sa_family следует указать значением AF_INET sin_addr это ip адресс нужного нам компьютера. Для преобразования текстовой строки в ip адресс используем функцию StrToNetAddr. sin_port это порт по которому мы будем передавать данные. Для преобразования номера порта в нужное значение нам понадобиться функция htons
Для приёма и посылки данных будем использовать функции fprecv и fpsend
function fprecv(s: cint; buf:pointer; len:size_t; flags: cint) : ssize_t
function fpsend(s: cint; msg:pointer; len:size_t; flags: cint) : ssize_t
Где s это сам сокет, второй параметр это указатель на буфер в котором содержаться данные (например массив символов), третий длина получаемого или отправляемого сообщения, четвертый параметр не будем использовать и обозначим его нулём.
Для закрытия сокета вызовем функцию
functionCloseSocket(Sock: LongInt) : LongInt
Пример:
program Client;
{$MODE OBJFPC}
uses Sockets;
const len =128;
var s:TSocke; sa:sockaddr; msg:array [0..len-1] of char; ip:string; slen:tsocklen;
fpaccept - прием полностью установленного соединения
fprecv - чтение запроса
fpsend - посылка ответа
CloseSocket - закрытие сокета
Первую функцию мы разобрали в первой части статьи. Используем аналогично как и с программой-клиентом. Так же надо заполнить запись sockaddr. О которой тоже было сказано в первой части статьи. За исключением поля sin_addr, его надо заполнить так sin_addr.s_addr:=htonl(INADDR_ANY). Константа INADDRR_ANY означает что принимаються соединения с любого адресса.
function fpbind(s: cint; addrx: psockaddr; addrlen: TSockLen) : cint
1 параметр это сокет
2 параметр указатель на запись типа sockaddr
3 размер этой записи (как в примере программы клиента используем sizeof(sockaddr) )
В случае успешного завершения возвращает ноль.
function fplisten(s: cint; backlog: cint) : cint
Переводит сокет в слушающее состояние и устанавливает максимальный размер очереди соединений - параметр backlog.
function fpaccept(s: cint;addrx: psockaddr; addrlen: pSockLen) : cint
Выбирает первый запрос из очереди, возвращает переменную сокет клиента, информацию заносит во второй параметр - указатель на запись sockaddr и её длину в addrlen.
Надо заметить что в этой функции последний параметр определён как указатель на переменную типа socklen.
Дальше так же как и с программой клиентом. Посылку и приём сообщений осуществляем с помощью функция fpsend и fprecv. И закрываем сокеты с помощью CloseSocket.
В качестве примера предоставлю вам программу сервер которая прослушивает порт 80. Этот порт используют веб-сервера, а значит и браузеры которые к ним подключаются. Поэтому я подключусь к своей программе через Google Chrome. И мы сможем увидеть запрос браузера.