Este programa de demonstracao estabelece um conexao socket para um servidor de ECHO em "outro computador" usando o protocolo TCP. Ele estabelece a comunicao , entao le uma linha da entrada padrao , envia esta linha para o Servidor Echo pelo socket e le a resposta do Echo. Isto é repetido ate se digitar a linha "quit".
/*
SOCKPROG.CPP
A interface do aplicativo e via "Microsoft C++ QuickWin
text window."
Testado e compilado no Microsoft Visual C++ 1.0 Standard Version
Copyright 1995 by Ken Coviak
Prepared for CS 671, Grand Valley State University
traduzido por Alex Borges.
original com instrucoes e arquivos para downlod
http://www.csis.gvsu.edu/~erickson/NetworkingArchives/WindowsSockets/KenCoviak/winsockp.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <winsock.h>
#define NUL '\0' /* ASCII NUL character */
/* function prototypes = independente da aplicao, sempre aparece */
void do_sock(
SOCKET sock ); /* socket to read and write */
void pWSAerror(
char *text ); /* error message text */
/* programa principal */
void main()
{
char *argv[] = { /* fake command argument list */
"sockprog", /* this program's name */
"river.it.gvsu.edu", /* host name, se quiser testar na mesma maquina use "localhost" ou endereco de loopback 127.0.0.1 */
"echo" /* echo service name */
};
/* estruturas que aprecem indepentede da aplicacao */
WORD wVersionRequested; /* requested version WinSock API */
WSADATA wsadata; /* dados da Windows Sockets API*/
SOCKET sock; /* descritp de socket */
struct hostent FAR *hp; /* ptr para informacoes do host */
struct servent FAR *sp; /* ptr para inf. do servico */
struct sockaddr_in server; /* endereco do socket e porta */
int stat; /* valor de status */
/* Enviar uma msg para a janela de texto (stdin/stderr/stdout) */
printf( "SOCKPROG Windows Socket Demo Program (QuickWin).\n" );
/*------------------------------------------------------*/
/* Incializar a Windows Sockets API. independente da aplicacao */
/* Procurando por API version 1.1 */
/*------------------------------------------------------*/
printf( "Starting WinSock API...\n" );
wVersionRequested = 0x0101;
stat = WSAStartup( wVersionRequested, &wsadata );
if (stat != 0)
{
printf( "No usable WINSOCK.DLL found\n" );
exit( 1 );
}
else if (LOBYTE( wsadata.wVersion) != 1 &&
HIBYTE( wsadata.wVersion) != 1)
{
printf( "WINSOCK.DLL does not support version 1.1\n" );
WSACleanup();
exit( 1 );
}
printf("WINSOCK description: %s\n", wsadata.szDescription);
printf("WINSOCK vendor info: %s\n", wsadata.lpVendorInfo);
/*------------------------------------------------------*/
/* Criar o socket - independente da aplicacao */
/* para udp use SOCK_DGRAM e para TCP SOCK_STREAM */
/*------------------------------------------------------*/
sock = socket( AF_INET, SOCK_STREAM, 0 );
if (sock == INVALID_SOCKET)
{
pWSAerror( "could not create socket" );
WSACleanup();
exit( 1 );
}
/*------------------------------------------------------*/
/* Conectar (e associar) o socket ao servico e servidor.*/
/* Tambem independente da aplicacao */
/*------------------------------------------------------*/
hp = gethostbyname( argv[1] ); /* pegar o host pelo nome . se for a maquna local = "localhost"*/
if (hp == NULL)
{
printf( "could not get host by name %s\n", argv[1] );
pWSAerror( "no host" );
WSACleanup();
exit( 1 );
}
memset( &server, 0, sizeof(server) );
memcpy( &server.sin_addr, hp->h_addr, hp->h_length );
server.sin_family = hp->h_addrtype;
sp = getservbyname( argv[2], "tcp" );
if (sp == NULL)
{
if (isdigit(*(argv[2])))
/* get service by number */
/* we need to swap byte order here */
server.sin_port = htons( atoi(argv[2]) );
else
{
printf( "could not find tcp service %s\n", argv[2] );
pWSAerror( "no service" );
WSACleanup();
exit( 1 );
}
}
else
server.sin_port = sp->s_port;
stat = connect( sock, (const struct sockaddr FAR *)&server,
sizeof(server) );
if (stat != 0)
{
pWSAerror( "could not connect" );
WSACleanup();
exit( 1 );
}
printf( "successful socket established\n" );
/*------------------------------------------------------*/
/* Ler da entrada padrao e enviar pelo socket */
/* ler do socket e enviar para a saida padrao */
/* essa é a aplicacao e é a parte que muda realmente */
/*------------------------------------------------------*/
do_sock( sock );
/*------------------------------------------------------*/
/* Terminar o programa fechando o socket, etc */
/*------------------------------------------------------*/
shutdown( sock, 2 );
closesocket( sock );
WSACleanup();
exit( 0 );
}
/* esta é a funcao que implemtnea a aplicacao */
/* ler do stdin e escrever p/ o socket e o inverso */
/* assume-se que o nro. de caracteres enviados e o mesmo */
/* que vamos receber. pode acontecer espera infinita neste ponto*/
#define MAXLINE 256
void do_sock(
SOCKET sock ) /* socket para ler e escrever = indepentede da aplicacao quando se quer ler ou escrever*/
{
int loopy; /* loop control */
int nb; /* numero de bytes */
char buffer[MAXLINE]; /* linha lida */
int bufcnt; /* no. de carc. no buffer */
char sockbuf[MAXLINE]; /* carac. lidos do socket */
int sockcnt; /* no. de carac no sockbuf */
/* Repeat until "quit" is entered. */
loopy = 1;
while (loopy)
{
/*--------------------------------------------------*/
/* Pega uma linha da stdin. se for a string */
/* "quit" ou uma linha vazia, vamos terminar a aplicacao */
/* De outra forma,vamos continuar e enviar */
/* a linha para o servidor de echo */
/*--------------------------------------------------*/
printf("Enter command for server (or quit)\n");
if (gets( buffer ) == NULL)
loopy = 0;
else if (strcmp( buffer, "quit" ) == 0)
loopy = 0;
else
{
/*----------------------------------------------*/
/* envia a linha para para o servidor ECHO */
/*----------------------------------------------*/
bufcnt = strlen( buffer );
nb = send( sock, buffer, bufcnt, 0 );
if (nb != bufcnt)
{
pWSAerror( "error writing to socket" );
return;
}
/*----------------------------------------------*/
/* le a resposta do servidor de Echo */
/* Note que se nao temos o nro esperado de caracteres */
/* de volta, vamos esperar indefinidamente */
/*----------------------------------------------*/
sockcnt = 0;
while (sockcnt < bufcnt)
{
nb = recv( sock, &sockbuf[sockcnt],
MAXLINE-sockcnt-1, 0 );
if (nb == SOCKET_ERROR)
{
pWSAerror( "error reading from socket" );
return;
}
else if (nb == 0) /* socket closed by server */
return;
else /* read OK, inc char count */
sockcnt += nb;
/*------------------------------------------*/
/* Escreve a resposta para saida padrao. */
/*------------------------------------------*/
sockbuf[sockcnt] = NUL;
printf( "%s\n", sockbuf );
}
}
} /* end while loopy */
return;
}
/* A funcao pWSAerror é usada para imprimir um Windows Sockets*/
/* API error message. Esta funcao é usada no lugar de perror */
/* porque a WinSock API retorna seus erros via errno */
void pWSAerror(
char *text ) /* error message text to display */
{
int err; /* Winsock error code */
err = WSAGetLastError();
printf( "%s, error %d\n", text, err );
return;
}