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

       

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


Функция main в каркасе UDP-клиента выполняет в основном запись в поля переменной peer указанных адреса и номера порта сервера и получает сокет типа SOCK_DGRAM. Она показана в листинге 2.10. Весь остальной код каркаса такой же, как для .

Листинг 2.10. Функция main из каркаса udpclient.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, "udp" );

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

8    if ( !isvalidsock( s ) )

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

10   client( s, &peer ) ;

11   exit( 0 ) :

12   }

Теперь можно протестировать одновременно этот каркас и программу udphello, для чего необходимо скопировать udpclient.skel в файл udphelloc.с и вместо клиентской заглушки подставить такой код:

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



{

 int rc;

 int peerlen;

 char buff [ 120 ];

 peerlen = sizeof( *peerp );

 if ( sendto( s, "", 1, 0, ( struct sockaddr * )peerp,

  peerlen ) < 0 )

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

 rc= recvfrom( s, buf, sizeof( buf ), 0,

  ( struct sockaddr * )peerp, &peerlen );

 if ( rc >= 0 )

  write ( 1, buf, rc );

 else

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

}

Функция client посылает серверу нулевой байт, читает возвращенную датаграмму, выводит ее в стандартное устройство вывода и завершает программу. Функции recvfrom в коде udphello вполне достаточно одного нулевого байта. После его приема она возвращает управление основной программе, которая и посылает ответную датаграмму.

При одновременном запуске обеих программ выводится обычное приветствий

bsd: $ udphello 9000 &

[1] 448

bsd: $ updhelloc localhost 9000

hello, world

bsd: $

Как всегда, следует вынести стартовый код из main в библиотеку. Обратите внимание, что библиотечной функции, которой дано имя udp_client (листинг 2.11), передается третий аргумент - адрес структуры sockaddr_in; в нее будет помещен адрес и номер порта, переданные в двух первых аргументах.

#include "etcp.h"

SOCKET udp_client( char *host, char *port,

struct sockaddr_in *sap );

Возвращаемое значение: UDP-сокет и заполненная структура sockaddr_in (в случае ошибки завершает программу).

Листинг 2.11. Функция udp_client

1    SOCKET udp_client( char *hname, char *sname,

2    struct sockaddr_in *sap )

3    {

4    SOCKET s;

5    set_address( hname, sname, sap, "udp" );

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

7    if ( !isvalidsockt ( s ) )

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

9    return s;

10   }



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