Эффективное программирование TCP-IP

       

Каркас TCP-клиента


Рассмотрим каркас приложения TCP-клиента (листинг 2.6). Если не считать Функции main и замены заглушки server заглушкой client, то код такой же, как для каркаса TCP-сервера.

Листинг 2.6. Функция main из каркаса tcpclientskel

tcpclient. skel

1    int main( int  argc, char **argv )

2    {

3    struct sockaddr_in peer;

4    SOCKET s;

5    INIT ( ) ;

6    set_address(argv[ 1 ], argv[ 2 ], &peer, "tcp");

7    s = socket( AF_INET, SOCK_STREAM, 0 );

8    if ( !isvalidsock( s ) )

9      error( 1, errno, "ошибка  вызова  socket" );

10   if ( connect( s, ( struct sockaddr * )&peer;

11     sizeof( peer ) ) )

12   error ( 1, errno, "ошибка вызова connect" );

13   client ( s, &peer );



14   EXIT ( 0 );

15   }

tcp_dient.skel

6-9 Как и в случае tcpserver.skel, записываем в поля структуры sockaddr_in указанные адрес и номер порта, после чего получаем сокет.

10-11 Вызываем connect для установления соединения с сервером.

13 После успешного возврата из connect вызываем заглушку client передавая ей соединенный сокет и структуру с адресом сервера.

Протестировать клиент можно, скопировав каркас в файл helloc.с и дописав в заглушку следующий код:

static void client ( SOCKET s, struct sockaddr_in *peerp )

{

 int rc;

 char buf[120];

 for ( ; ; )

 {

  rc = recv( s, buf, sizeof( buf ), 0 );

  if ( rc <= 0 )

   break;

  write( 1, buf, rc );

 }

}

Этот клиент читает из сокета данные и выводит их на стандартный вывод до тех пор, пока сервер не пошлет конец файла (EOF). Подсоединившись к серверу hello, получаете:

bsd: $

hello localhost 9000

hello, world

bsd: $

Поместим фрагменты кода tcpclient.skel в библиотеку, так же, как поступили с каркасом tcpclient.skel. Новая функция- tcp_client, приведенная в листинге 2.7, имеет следующий прототип:

#include "etcp.h"

SOCKET  tcp_client( char *host, char *port );

Возвращаемое значение: соединенный сокет (в случае ошибки завершает программу).

Как и в случае tcp_server, параметр host содержит либо имя, либо IР-адрес хоста, а параметр port - символическое имя сервиса или номер порта в виде ASCII-строки.

Листинг 2.7. Функция tcp_client

1    SOCKET tcp_client( char *hname, char *sname )

2    {

3    struct sockaddr_in peer;

4    SOCKET s;

5    set_address( hname, sname, &peer, "tcp" );

6    s = socket( AF_INET, SOCK_STREAM, 0 );

7    if ( !isvalidsock( s ) )

8      error( 1, errno, "ошибка вызова socket" );

9    if ( connect( s, ( struct sockaddr * )&peer,

10     sizeof( peer ) ) )

11     error( 1, errno, "ошибка вызова connect" );

12   return s;

13   }



Содержание раздела