Для получения целостной картины кратко повторим все сказанное. Для установления соединения сервер должен, во-первых, создать сокет с помощью функции 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.