Для получения целостной картины кратко повторим все сказанное. Для установления соединения сервер должен, во-первых, создать сокет с помощью функции socket
, а во-вторых, привязать его к адресу с помощью функции bind
. Далее сокет должен быть переведен в режим ожидания с помощью listen
, а потом с помощью функции accept
создается новый сокет, обслуживающий соединение, установленное клиентом. После этого сервер может обмениваться данными с клиентом. Клиент же должен создать сокет, при необходимости привязки к конкретному порту вызвать bind
, и затем вызвать connect
для установления соединения. После успешного завершения этой функции клиент может обмениваться данными с сервером. Это иллюстрируют листинги 2.11 и 2.12.
var
S, AcceptedSock: TSocket;
Addr: TSockAddr;
Data: TWSAData;
Len: Integer;
begin
WSAStartup($101, Data);
S := socket(AF_INET, SOCK_SТREAМ, 0);
Addr.sin_family := FF_INET;
Addr.sin_port := htons(3030);
Addr.sin_addr.S_addr := INADDR_ANY;
FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);
bind(S, Addr, SizeOf(TSockAddr));
listen(S, SOMAXCONN);
Len := SizeOf(TSockAddr);
AcceptedSock := accept(S, @Addr, @Len);
{
Теперь Addr содержит адрес клиента, с которым установлено соединение, а AcceptedSock - дескриптор, обслуживающий это соединение. Допустимы следующие действия:
send(AcceptedSock, ...) - отправить данные клиенту
recv(AcceptedSock, ...) - получить данные от клиента
accept(...) - установить соединение с новым клиентом
}
Здесь сокет сервера привязывается к порту с номером 3030. В общем случае разработчик сервера сам должен выбрать порт из диапазона 1024–65 535.
var
S: TSocket;
Addr: TSockAddr;
Data: TWSAData;
begin
WSAStartup($101, Data);
S := socket(AF_INET, SOCK_STREAM, 0);
Addr.sin_family := AF_INET;
Addr.sin_port := htons(3030);
Addr.sin_addr.S_addr := inet_addr(...);
FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);
connect(S, Addr, SizeOf(TSockAddr));
{
Теперь соединение установлено. Допустимы следующие действия:
send(S, ...) - отправить данные серверу
recv(S, ...) — получить данные от сервера
}
В приведенном коде для краткости опущены проверки результатов функций с целью обнаружения ошибок. При написании серьезных программ этим пренебрегать нельзя. Блок-схема действии клиента и сервера приведена на рис. 2.3.