Каркас 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 }