Теперь переходим к созданию клиентской части. Для этого создадим новый проект и поместим на форму строку ввода (для ввода адреса сервера) и кнопку для соединения с сервером и отправки ему команд. По нажатии этой кнопки необходимо написать код из листинга 4.5.

Листинг 4.5. Соединение с сервером, прием и передача данных

procedure TTCPClientForm.btSendClickCSender: TObject): var
wData: WSADATA: sServerListen: TSOCKET. server_addr- sockaddr_in;
iRet: Integer:

sRecvBuff: array [0..255] of char: begin // Загрузка WinSock

if WSAStartup(MAKEWORDd.l). wData) <> 0 then begin MessageBox(0. 'He могу загрузить WmSock". 'Ошибка'. 0): exit:

end:

// Создание сокета

sServerListen := socket(AF_INET. SOCK_STREAM. IPPR0T0JP), if sServerListen = INVALID_SOCKET then begin MessageBoxCO "Ошибка создания сокета". "Ошибка". 0): exit:

end:

// Заполнение структуры адреса server_addr.sin_addr.s_addr -= htonl(INADDR_ANY)' server_addr.sin_family .= AF_INET; server_addr.sin_port := htons(5050): server_addr sin_addr := LookupName(edServer.Text) // Соединение с сервером

if (connect(sServerListen, server_addr. sizeof(server_addr))
= SOCKETJRROR) then
begin
TestWi nSockErrorC'Send');
exit:
end:
// Отправка данных sRecvBuff := 'get';
iRet •= sendCsServerListen, sRecvBuff. 3. 0):

if (iRet = SOCKETJRROR) then begin MessageBoxCO. 'Ошибка передачи данных', 'Внимание!!!' 0). exit

end.

// Получение данных

iRet := recv(sServerListen, sRecvBuff. 1024, 0);

if (iRet = SOCKETJRROR) then begin MessageBox(0, 'Ошибка получения данных' 'Внимание!!!' 0): exit:

end:
edServer.Text •= sRecvBuff; // Отключение от сервера CloseSocket(sServerListen);
end:

Начало кода клиентской программы совпадает с кодом сервера. Мы также загружаем сетевую библиотеку Windows и создаем сокет. Разница начинается с заполнения структуры адреса, потому что теперь недостаточно указать только порт. Необходимо еще заполнить поле sin_addr, в котором указывается адрес сервера. В данном примере это делается следующей строкой:

server_addr.sin_addr := LookupName(edServer.Text);

Функция LookupName определяет, указан ли в качестве адреса IP, в этом случае он переводится в нужный формат с помощью функции gethostbyname. Если указано символьное имя, то его перевод в IP-адрес осуществляется той же самой функцией. Текст функции LookupName приведен в листинге 4.6.

Листинг 4.6. Определение IP-адреса сервера

function LookupName(name:String): TInAddr: var
HostEnt: PHostEnt: InAddr: TInAddr;
begin
if name[4]='.' then
InAddr.s_addr := inet_addr(PChar(name))
else
begin
HostEnt := gethostbyname(PChar(name));
Fill Char(InAddr. SizeOf(InAddr). 0). if HostEnt <>
nil then begin
with InAddr. HostEnt* do begin
S_un_b s_b! = h_addr*[0], S_un_b s_b2 = h_addr*[l] S_un_b.s_b3 = h_addr*[2]: S_un_b.s_b4 .= h_addrA[3]:
end;
end
end;
Result •= InAddr.
end;

После определения адреса сервера сразу же вызывается функция connect для соединения с сервером. Если соединение произошло удачно, то можно обмениваться данными с использованием уже знакомых нам функций send и recv.

Напоследок хочу сделать одно замечание. Когда используете функцию send, во втором параметре нужно указывать буфер с данными, которые надо передать по сети. Используйте в этом параметре только тип PChar. Если указать строку String, то сервер увидит не совсем то, что вы отправляли, а точнее сказать, может увидеть бесполезный "мусор".

ПРИМЕЧАНИЕ

Исходный код рассмотренного здесь примера находится на компакт-диске в каталоге Sources\ch04\TCPCIient.

4.10.3. Тестирование сервера || Оглавление || 4.12. Пример использования UDP-протокола


Delphi в шутку и всерьез: что умеют хакеры



Новости за месяц

  • Декабрь
    2021
  • Пн
  • Вт
  • Ср
  • Чт
  • Пт
  • Сб
  • Вс
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31