Está en la página 1de 12

CORE Metadata, citation and similar papers at core.ac.

uk
Provided by Universidad Distrital de la ciudad de Bogotá: Open Journal Systems

A T Implementación cliente servidor mediante sockets

Implementación cliente
servidor mediante sockets
Client-server implementation using sockets

Héctor Julio Fúquene Ardila*

Fecha de recepción: septiembre 30 de 2011


Fecha de aceptación: noviembre 4 de 2011

Resumen
Este artículo pretende hacer visibles los requerimientos tanto físicos, lógicos y
funcionales necesarios para establecer una comunicación entre
dos computadores utilizando sockets; se plantean los diferentes
protocolos mediante los cuales se puede realizar su implemen-
tación; además, se presentan las principales características téc-
nicas a tener en cuenta y se realiza la implementación mediante
el uso del lenguaje de programación como C++.

Palabra clave
Programa cliente, programa servidor, comunicaciones, puerto
lógico, protocolo, dirección IP.

Abstract
This article aims to make visible the requirements of both physical, logi-
cal and functional requirements for communication between two com-
puters using sockets, raised different protocols by which implementa-
tion can be done, also presents the main technical features to consider
and implementation is done using the programming language C + +.

Keywords
Client (customer) program, server program, communications, logic
port, protocol, IP address.

* Ingeniero de sistemas, Magister en teleinformática, miembro del grupo de investigación IAFT, docente de palnta
48
48 de la Universidad Distrital Francisco José de Caldas. hfuquene@udistrital.edu.co

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


HÉCTOR JULIO FÚQUENE ARDILA V Í N C U L O S
JU L I O - D I C I EM B R E D E 2 0 1 1
VOLUMEN 8 NÚMERO 2

Introducción ¿Qué son los sockets?


La comunicación entre entidades abstrac- Podemos encontrar diferentes definiciones,
tas (PCs) se logra utilizando diferentes téc- algunas de ellas son:
nicas, una de ellas es utilizando sockets,
que consiste en configurar una red cliente Los sockets son un método de comunica-
servidor para establecer el flujo de infor- ción entre un programa de cliente y uno
mación entre transmisor y receptor. de servidor a través de una red. Un soc-
ket se define como “el extremo de una co-
Es posible utilizar un protocolo orientado nexión”.
a conexión como TCP (Transfer Control
Protocol) o uno no orientado a conexión Un socket, es un método para la comuni-
como UDP (User Datagram Protocol), la cación entre un programa del cliente y un
diferencia entre los dos es la fiabilidad que programa del servidor en una red. Un soc-
se puede garantizar con un protocolo que ket se define como el punto final en una
garantice la conexión con el extremo recep- conexión. Los sockets se crean y se utilizan
tor, es decir que sea orientado a conexión. con un sistema de peticiones o de llamadas
de función a veces llamados interfaz de pro-
Para que dos aplicaciones puedan inter- gramación de aplicación de sockets (API,
cambiar información entre sí se necesita: Application Programming Interface).
• Un protocolo de comunicación co-
Un socket es también una dirección de
mún a nivel de red y a nivel de trans-
Internet, combinando una dirección IP (la
porte.
dirección numérica única de cuatro octetos
• Una dirección del protocolo de red que identifica a un computador particular
que identifique a cada uno de los en Internet) y un número de puerto (el nú-
computadores. mero que identifica una aplicación de In-
ternet particular)
• Un número de puerto que identifique
la aplicación dentro del computador. Un socket es un punto final de un enlace
de comunicación de dos vías entre dos pro-
Los socket se utilizan para poder enviar gramas que se ejecutan a través de la red.
órdenes a un servidor que está atendiendo
nuestras peticiones. Por lo tanto, un socket
quedaría definido por una dirección IP (La ¿Cómo se establece
del equipo que actúa como servidor), un la comunicación con sockets?
protocolo y un número de puerto (El uti-
lizado para acceder a un servicio determi- El cliente y el servidor deben ponerse de
nado). acuerdo sobre el protocolo que utilizarán.

A su vez, los sockets están basados en el Hay dos tipos de socket:


protocolo de comunicaciones utilizado en
Internet: TCP (Transmisión Control Proto- Orientado a conexión
col).
Establece un camino virtual entre servidor
La función del protocolo TCP es, ni más ni y cliente, fiable, sin pérdidas de informa-
menos que la de traer y llevar información ción ni duplicados, la información llega
desde un servidor a un cliente y viceversa en el mismo orden que se envía. El cliente
utilizando los diferentes protocolos utiliza- abre una sesión en el servidor y este guar-
dos por cada servicio. da un estado del cliente.
49
49

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


A T Implementación cliente servidor mediante sockets

Orientado a no conexión La comunicación entre procesos a través de


sockets se basa en la filosofía cliente-servi-
Envío de datagramas de tamaño fijo. No es dor: un proceso en esta comunicación ac-
fiable, puede haber pérdidas de información tuará de proceso servidor creando un socket
y duplicados, y la información puede llegar cuyo nombre conocerá el proceso cliente, el
en distinto orden del que se envía. No se guar- cual podrá “hablar” con el proceso servi-
da ningún estado del cliente en el servidor, dor a través de la conexión con dicho socket
por ello, es más tolerante a fallos del sistema. nombrado.
Lossockets no son más que puntos o meca-
nismos de comunicación entre procesos que El proceso crea un socket sin nombre cuyo
permiten que un proceso hable (emita o re- valor de vuelta es un descriptor sobre el
ciba información) con otro proceso incluso que se leerá o escribirá, permitiéndose una
estando estos procesos en distintas máqui- comunicación bidireccional, característica
nas. Esta característica de interconectividad propia de los sockets. El mecanismo de co-
entre máquinas hace que el concepto de soc- municación vía sockets tiene los siguientes
ket nos sirva de gran utilidad. pasos:

Un socket es al sistema de comunicación entre • El proceso servidor crea un socket con


computadores, lo que un buzón o un teléfono nombre y espera la conexión.
es al sistema de comunicación entre personas: • El proceso cliente crea un socket sin
un punto de comunicación entre dos agentes nombre.
(procesos o personas respectivamente) por el
cual se puede emitir o recibir información. • El proceso cliente realiza una petición
de conexión al socket servidor.
La arquitectura cliente-servidor • El cliente realiza la conexión a través de
su socket mientras el proceso servidor
Es un modelo de aplicación distribuida en el mantiene el socket servidor original
que las tareas se reparten entre los provee- con nombre.
dores de recursos o servicios, llamados ser-
vidores, y los demandantes, llamados clien- Es muy común en este tipo de comunicación
tes. Un programa cliente realiza peticiones lanzar un proceso hijo, una vez realizada la
a otro programa, el servidor, que le da res- conexión, que se ocupe del intercambio de
puesta. Esta idea también se puede aplicar información con el proceso cliente mientras
a programas que se ejecutan sobre una sola el proceso padre servidor sigue aceptando
máquina, aunque es más ventajosa en un conexiones. Para eliminar esta característica
sistema operativo multiusuario distribuido se cerrará el descriptor del socket servidor
a través de una red de computadores. con nombre en cuanto realice una conexión
con un proceso socket cliente.
En esta arquitectura la capacidad de proceso
está repartida entre los clientes y los servi- El Servidor
dores. La separación entre cliente y servidor
es una separación de tipo lógico, donde el A partir de este punto comenzamos con lo
servidor no se ejecuta necesariamente so- que es la programación en C++ de los soc-
bre una sola máquina ni es necesariamente kets. Se debe poseer conocimientos de C++,
un sólo programa. Los tipos específicos de de esta forma será más fácil el atender el
servidores incluyen los servidores webs, los procedimiento a seguir.
servidores de archivo, los servidores del co-
rreo, entre otros. Mientras que sus propósi- Con C++ en Unix/Linux, los pasos que debe
tos varían de unos servicios a otros, la arqui- seguir un programa servidor son los siguien-
50
50 tectura básica seguirá siendo la misma. tes:

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


HÉCTOR JULIO FÚQUENE ARDILA V Í N C U L O S
JU L I O - D I C I EM B R E D E 2 0 1 1
VOLUMEN 8 NÚMERO 2

Realizar la apertura de un socket, median- El Cliente


te la función socket(). Esta función devuel-
ve un descriptor de archivo normal, como Los pasos que debe seguir un programa
puede devolverlo open(). La función soc- cliente son los siguientes:
ket() no hace absolutamente nada, salvo
devolvernos y preparar un descriptor de Realizar la apertura de un socket, como el
fichero que el sistema posteriormente aso- servidor, por medio de la función socket()
ciará a una conexión en red.
Solicitar conexión con el servidor por me-
Avisar al sistema operativo de que hemos dio de la función connect(). Dicha función
abierto un socket y queremos que asocie quedará bloqueada hasta que el servidor
nuestro programa a dicho socket. Se con- acepte nuestra conexión o bien si no hay
sigue mediante la función bind(). El siste- servidor en el sitio indicado, saldrá dando
ma todavía no atenderá a las conexiones un error. En esta llamada se debe facilitar
de clientes, simplemente anota que cuando la dirección IP del servidor y el número de
empiece a hacerlo, tendrá que avisarnos. Es servicio que se desea.
en esta llamada cuando se debe indicar el
Escribir y recibir datos del servidor por
número de servicio al que se quiere aten-
medio de las funciones write() y read().
der.
Cerrar la comunicación por medio de clo-
Avisar al sistema de que comience a aten-
se().
der dicha conexión de red. Se consigue me-
diante la función listen(). A partir de este Como se puede apreciar, el procedimiento
momento el sistema operativo anotará la en el cliente es mucho más sencillo que el
conexión de cualquier cliente para pasár- servidor, más sin embargo, se debe como
nosla cuando se lo pidamos. Si llegan clien- mínimo garantizar en los dos extremos, un
tes más rápido de lo que somos capaces de paso de establecimiento de la comunica-
atenderlos, el sistema operativo hace una ción, uno de transferencia de información
“cola” con ellos y nos los irá pasando según y uno mediante el cual se libera la comuni-
vayamos pidiéndolo. cación.

Pedir y aceptar las conexiones de clientes


Tipos de sockets
al sistema operativo. Para ello hacemos una
llamada a la función accept(). Esta función Todo socket viene definido por dos caracte-
le indica al sistema operativo que nos dé al rísticas fundamentales: El tipo del socket y
siguiente cliente de la cola. Si no hay clien- el dominio del socket.
tes se quedará bloqueada hasta que algún
cliente se conecte. El tipo del socket, que indica la naturale-
za del mismo, el tipo de comunicación que
Escribir y recibir datos del cliente, por me- puede generarse entre los sockets.
dio de las funciones write() y read(), que
son exactamente las mismas que usamos El dominio del socket especifica el conjunto
para escribir o leer de un archivo. Obvia- de sockets que pueden establecer una co-
mente, tanto cliente como servidor deben municación con el mismo.
saber qué datos esperan recibir, qué datos
deben enviar y en qué formato. Los sockets definen las propiedades de las
comunicaciones en las que se ven envuel-
Cierre de la comunicación y del socket, por tos, esto es, el tipo de comunicación que se
medio de la función close(), que es la mis- puede dar entre cliente y servidor. Estas
ma que sirve para cerrar un archivo. pueden ser: 51
51

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


A T Implementación cliente servidor mediante sockets

Fiabilidad de transmisión. void InsertarMenu(HWND);


Mantenimiento del orden de los datos. char enviardata(HWND, char*);
No duplicación de los datos. WSADATA wsa;
El “Modo Conectado” en la comunicación. SOCKET sock;
Envío de mensajes urgentes. struct sockaddr_in local;
int len=0;
Y cómo Logran “hablar” char Buffer[500000];
los computadores. int WINAPI WinMain (HINSTANCE hThi-
sInstance, HINSTANCE hPrevInstance,
A continuación se describe detalladamen- LPSTR lpszArgument, int nFun
te cómo se establece la comunicación entre sterStil)
dos procesos residentes en un mismo PC o
{
en máquinas diferentes. Se describe las fun-
ciones utilizadas, haciendo énfasis en los pa- HWND hwnd;
rámetros utilizados y en el orden lógico de MSG messages;
invocación. Inicialmente, se hace la descrip- WNDCLASSEX wincl;
ción del proceso realizado en el servidor y wincl.hInstance = hThisInstance;
posteriormente lo que ocurre en el cliente.
wincl.lpszClassName = szClassName;
A continuación se presenta el código en C++ wincl.lpfnWndProc = WindowProce-
para Windows, utilizando ambiente gráfico. dure;
En Windows es indispensable utilizar la li- wincl.style = CS_DBLCLKS;
brería winsock2.h y utilizar el software Dev wincl.cbSize = sizeof (WNDCLASSEX);
C++ generando un proyecto.
wincl.hIcon = LoadIcon (NULL, IDI_AP-
PLICATION);
Servidor.
wincl.hIconSm = LoadIcon (NULL, IDI_
//nombrar este código con el nombre ser- APPLICATION);
ver.cpp wincl.hCursor = LoadCursor (NULL,
IDC_ARROW);
#include <windows.h>
wincl.lpszMenuName = NULL;
#include <iostream>
wincl.cbClsExtra = 0;
#include <winsock2.h>
wincl.cbWndExtra = 0;
#include <ws2tcpip.h>
wincl.hbrBackground = (HBRUSH) CO-
#include <stdlib.h>
LOR_BACKGROUND;
#include <stdio.h>
if (!RegisterClassEx (&wincl))
#define DEFAULT_BUFLEN 512
return 0;
#define DEFAULT_PORT “9999”
hwnd = CreateWindowEx (0, szClass
#define SERVER_ICON 100 Name,
#define CM_INICIAR 101 “Server”,WS_OVERLAPPEDWINDOW,
#define CM_SALIR 102 CW_USEDEFAULT, CW_USE
#define CM_CERRARCONEXION 103 DEFAULT, 640, 480, HWND_DES-
#define CM_ENVIARDATA 104 KTOP, NULL,
LRESULT CALLBACK WindowProcedure hThisInstance,
(HWND, UINT, WPARAM, LPARAM); NULL
52
52 char szClassName[ ] = “Server”; );

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


HÉCTOR JULIO FÚQUENE ARDILA V Í N C U L O S
JU L I O - D I C I EM B R E D E 2 0 1 1
VOLUMEN 8 NÚMERO 2

InsertarMenu(hwnd); }
ShowWindow (hwnd, nFunsterStil); else
while (GetMessage (&messages, NULL, 0, {
0)) SendMessage(hwndSTATUS, WM_SET-
{ TEXT, 0, (long int) “INICIADO” );
TranslateMessage(&messages); }
DispatchMessage(&messages); len=sizeof(struct sockaddr);
} sock=accept(sock,(sockaddr*)&local,&le
return messages.wParam; n);
} SendMessage(hwndSTATUS, WM_SET-
TEXT, 0, (long int) “CONECTADO” );
struct thread1
while (len!=0)
{
{
HWND hwnd1;
len=recv(sock,Buffer,499999,0);
HWND hwnd2;
if (len>0)
HWND hwnd3;
{
};
Buffer[len]=0;
thread1 obj1;
SendMessage(hwndRECIBIDO, WM_SET-
UINT ThreadProc1(LPVOID lpvoid); TEXT, 0, (long int) Buffer );
UINT ThreadProc1(LPVOID lpvoid) }
{ Sleep(1);
thread1 *temp = (thread1*)lpvoid; }
HWND hwnd= temp->hwnd1; }
HWND hwndRECIBIDO = temp- LRESULT CALLBACK WindowProcedure
>hwnd2; (HWND hwnd, UINT message, WPARAM
HWND hwndSTATUS = temp->hwnd3; wParam, LPARAM lParam)
HDC hdc= GetDC(hwnd); {
WSAStartup(MAKEWORD(2,0),&wsa); static HINSTANCE hInstance;
sock=socket(AF_INET,SOCK_ char textoAENVIAR[500000];
STREAM,IPPROTO_TCP); HANDLE hThrd1,hThrd2;
local.sin_family = AF_INET; switch (message)
local.sin_addr.s_addr = INADDR_ANY; { case WM_CREATE:
local.sin_port = htons(9999); static HWND hwndENVIARDATA =
if (bind(sock, (SOCKADDR*) &local, CreateWindow
sizeof(local))==-1) ( “button”, “Enviar”,
{ WS_CHILD|WS_VISIBLE|BS_CENTER,
SendMessage(hwndSTATUS, WM_SET- 520, 395, 100, 30, hwnd, (HMENU)CM_
TEXT, 0, (long int) “ERROR” ); ENVIARDATA, hInstance, NULL
} );
if (listen(sock,1)==-1) static HWND
{ hwndRECIBIDO=CreateWindowEx
SendMessage(hwndSTATUS, WM_SET- ( WS_EX_CLIENTEDGE, “EDIT”,””,
TEXT, 0, (long int) “ERROR” ); WS_CHILD | WS_VSCROLL | ES_MUL- 53
53

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


A T Implementación cliente servidor mediante sockets

TILINE | WS_VISIBLE | WS_BORDER | PostQuitMessage(0);


WS_TABSTOP, break;
10, 10, 612, 275, hwnd, NULL, hInstance, case CM_CERRARCONEXION:
NULL closesocket(sock);
); WSACleanup();
static HWND break;
hwndENVIAR=CreateWindowEx
case CM_ENVIARDATA:
( WS_EX_CLIENTEDGE, “EDIT”,””,
GetWindowText(hwndENVIAR, textoA-
WS_CHILD | WS_VSCROLL | ES_MUL- ENVIAR, 500000);
TILINE | WS_VISIBLE | WS_BORDER |
enviardata(hwndENVIAR, textoAEN-
WS_TABSTOP,
VIAR);
10, 300, 497, 125, hwnd, NULL, hInstance,
break;
NULL );
}
static HWND
hwndSTATUS=CreateWindowEx break;
( WS_EX_CLIENTEDGE, case WM_DESTROY:
closesocket(sock);
“EDIT”,”STAND-BY”,
WSACleanup();
WS_CHILD | WS_VISIBLE | WS_BOR-
DER | WS_TABSTOP, PostQuitMessage (0);
520, 325, 100, 25, hwnd, NULL, hInstance, break;
NULL default:
); return DefWindowProc (hwnd, message,
break; wParam, lParam);
case WM_COMMAND: }
switch(LOWORD(wParam)) { return 0;
case CM_INICIAR: }
char enviardata(HWND hwndENVIAR,
// Run the first Thread
char *entrada)
obj1.hwnd1 = hwnd;
{
obj1.hwnd2 = hwndRECIBIDO;
send(sock,entrada,strlen(entrada),0);
obj1.hwnd3 = hwndSTATUS;
SendMessage(hwndENVIAR, WM_SET-
hThrd1 = CreateThread(NULL, 0, (LP- TEXT, 0, (long int) “ “ );
THREAD_START_ROUTINE) Threa-
}
dProc1,
void InsertarMenu(HWND hwnd)
(LPVOID)&obj1,
{
CREATE_SUSPENDED,
HMENU hMenu1, hMenu2;
NULL);
hMenu1 = CreateMenu();
ResumeThread(hThrd1);
hMenu2 = CreateMenu();
AppendMenu(hMenu2, MF_STRING, CM_
SetThreadPriority(hThrd1,THREAD_PRI-
INICIAR, “&Iniciar Server”);
ORITY_HIGHEST);
AppendMenu(hMenu2, MF_STRING, CM_
break;
CERRARCONEXION, “&Cerrar Conex-
case CM_SALIR: ion”);
closesocket(sock); AppendMenu(hMenu2, MF_SEPARATOR,
54
54 WSACleanup(); 0, NULL);

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


HÉCTOR JULIO FÚQUENE ARDILA V Í N C U L O S
JU L I O - D I C I EM B R E D E 2 0 1 1
VOLUMEN 8 NÚMERO 2

AppendMenu(hMenu2, MF_STRING, CM_ #define CM_ENVIARDATA 104


SALIR, “&Salir”); LRESULT CALLBACK WindowProcedure
AppendMenu(hMenu1, MF_STRING | MF_ (HWND, UINT, WPARAM, LPARAM);
POPUP, (UINT)hMenu2, “&Menu”); char szClassName[ ] = “Client”;
SetMenu (hwnd, hMenu1); void InsertarMenu(HWND);
} char enviardata(HWND, char*);
WSADATA wsa;
SOCKET sock;
int len;
char Buffer[500000];
struct hostent *host;
struct sockaddr_in direc;
int conex;
int WINAPI WinMain (HINSTANCE hThi-
sInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd;
Como se están ejecutando las dos aplicacio-
MSG messages;
nes en la misma máquina (cliente y servidor)
se debe iniciar de forma independiente. En WNDCLASSEX wincl;
la gráfica anterior aparece la interfaz inicial wincl.hInstance = hThisInstance;
del servidor. wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure;
El programa cliente se presenta wincl.style = CS_DBLCLKS;
a continuación: wincl.cbSize = sizeof (WNDCLASSEX);
wincl.hIcon = LoadIcon (NULL, IDI_APPLI-
//nombrar este código con el nombre clien-
CATION);
te.cpp
wincl.hIconSm = LoadIcon (NULL, IDI_
#include <windows.h>
APPLICATION);
#include <iostream>
wincl.hCursor = LoadCursor (NULL, IDC_
#include <winsock2.h> ARROW);
#include <ws2tcpip.h> wincl.lpszMenuName = NULL;
#include <stdlib.h> wincl.cbClsExtra = 0;
#include <stdio.h> wincl.cbWndExtra = 0;
#define DEFAULT_BUFLEN 512 wincl.hbrBackground = (HBRUSH) CO-
#define DEFAULT_PORT “9999” LOR_BACKGROUND;
#define CLIENT_ICON 100 if (!RegisterClassEx (&wincl))
#define CM_CONECTAR 101 return 0;
#define CM_SALIR 102 hwnd = CreateWindowEx (0, szClassName,
#define CM_CERRARCONEXION 103 “Client”, 55
55

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


A T Implementación cliente servidor mediante sockets

WS_OVERLAPPEDWINDOW, //se crea el socket


CW_USEDEFAULT, CW_USEDEFAULT, sock=socket(AF_INET,SOCK_
640, 480, HWND_DESKTOP, STREAM,IPPROTO_TCP);
LoadMenu(hThisInstance, “Menu”), if (sock==-1)
hThisInstance, {
NULL SendMessage(hwndSTATUS, WM_SET-
); TEXT, 0, (long int) “ERROR” );;
InsertarMenu(hwnd); }
ShowWindow (hwnd, nFunsterStil); // Se define la dirección a conectar que
hemos recibido desde el gethostbyname
while (GetMessage (&messages, NULL, 0,
0)) //y se decide que el puerto al que deberá
conectar es el 9999 con el protocolo ipv4
{
direc.sin_family=AF_INET;
TranslateMessage(&messages);
direc.sin_port=htons(9999);
DispatchMessage(&messages);
direc.sin_addr = *((struct in_addr *)host-
} >h_addr);
return messages.wParam; memset(direc.sin_zero,0,8);
} //Intentamos establecer la conexión
struct thread1 conex=connect(sock,(sockaddr *)&direc,
{ sizeof(sockaddr));
HWND hwnd1; if (conex==-1) //si no se ha podido conec-
HWND hwnd2; tar porque no se ha encontrado el host o no
HWND hwnd3; //está el puerto abierto
HWND hwnd4; {
}; SendMessage(hwndSTATUS, WM_SET-
thread1 obj1; TEXT, 0, (long int) “ERROR” );
UINT ThreadProc1(LPVOID lpvoid); }
UINT ThreadProc1(LPVOID lpvoid) else
{ {
thread1 *temp = (thread1*)lpvoid; SendMessage(hwndSTATUS, WM_SET-
TEXT, 0, (long int) “CONECTADO” );
HWND hwnd= temp->hwnd1;
}
HWND hwndSTATUS = temp->hwnd2;
len=sizeof(struct sockaddr);
HWND hwndIP = temp->hwnd3;
while (len!=0) //mientras estemos conec-
HWND hwndRECIBIDO = temp- tados con el otro pc
>hwnd4;
{
HDC hdc= GetDC(hwnd);
len=recv(sock,Buffer,499999,0); //recibi-
WSAStartup(MAKEWORD(2,2),&wsa); mos los datos
//resuelve el nombre de dominio local- if (len>0) //si seguimos conectados
host, esto se resolverá a 127.0.0.1
{
//host=gethostbyname(“127.0.0.1”);
Buffer[len]=0; //le ponemos el final de ca-
char ip[30]; dena
GetWindowText(hwndIP, ip, 30); SendMessage(hwndRECIBIDO, WM_SET-
56
56 host=gethostbyname(ip); TEXT, 0, (long int) Buffer );

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


HÉCTOR JULIO FÚQUENE ARDILA V Í N C U L O S
JU L I O - D I C I EM B R E D E 2 0 1 1
VOLUMEN 8 NÚMERO 2

} 520, 355, 100, 25, hwnd, NULL, hInstance,


Sleep(1); NULL
} );
} static HWND
LRESULT CALLBACK WindowProcedure hwndSTATUS=CreateWindowEx
(HWND hwnd, UINT message, WPARAM ( WS_EX_CLIENTEDGE,
wParam, LPARAM lParam) “EDIT”,”STAND-BY”,
{ WS_CHILD | WS_VISIBLE | WS_BOR-
static HINSTANCE hInstance; DER | WS_TABSTOP,
char textoAENVIAR[500000]; 520, 325, 100, 25, hwnd, NULL, hInstance,
HANDLE hThrd1,hThrd2; NULL
switch (message) );
{ break;
case WM_CREATE: case WM_COMMAND:
static HWND hwndENVIARDATA = switch(LOWORD(wParam)) {
CreateWindow case CM_CONECTAR:
( “button”, “Enviar”, obj1.hwnd1 = hwnd;
WS_CHILD|WS_VISIBLE|BS_CENTER, obj1.hwnd2 = hwndSTATUS;
520, 395, 100, 30, hwnd, (HMENU)CM_ obj1.hwnd3 = hwndIP;
ENVIARDATA, hInstance, NULL obj1.hwnd4 = hwndRECIBIDO;
); hThrd1 = CreateThread(NULL, 0,
static HWND (LPTHREAD_START_
hwndRECIBIDO=CreateWindowEx ROUTINE) ThreadProc1,
( WS_EX_CLIENTEDGE, “EDIT”,””, (LPVOID)&obj1, // param to thread
WS_CHILD | WS_VSCROLL | ES_MUL- func
TILINE | WS_VISIBLE | WS_BORDER | CREATE_SUSPENDED, // creation
WS_TABSTOP, flag
10, 10, 612, 275, hwnd, NULL, hInstance, NULL); //
NULL
ResumeThread(hThrd1);
);
static HWND SetThreadPriority(hThrd1,THREAD_PRI-
hwndENVIAR=CreateWindowEx ORITY_HIGHEST);
( WS_EX_CLIENTEDGE, “EDIT”,””, break;
WS_CHILD | WS_VSCROLL | ES_MUL- case CM_SALIR:
TILINE | WS_VISIBLE | WS_BORDER |
WS_TABSTOP, closesocket(sock);
10, 300, 497, 125, hwnd, NULL, hInstance, WSACleanup();
NULL PostQuitMessage(0); // envía un mensaje
); WM_QUIT a la cola de mensajes
static HWND hwndIP=CreateWindowEx break;
( WS_EX_CLIENTEDGE, case CM_CERRARCONEXION:
“EDIT”,”127.0.0.1”, closesocket(sock);
WS_CHILD | WS_VISIBLE | WS_BOR- WSACleanup();
DER | WS_TABSTOP, break; 57
57

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


A T Implementación cliente servidor mediante sockets

case CM_ENVIARDATA: En la gráfica siguiente visualizamos el pri-


GetWindowText(hwndENVIAR, textoA- mer pantallazo que presenta el programa
ENVIAR, 500000); cliente. El programa se puede correr en una
enviardata(hwndENVIAR, textoAEN- sola máquina con la dirección 127.0.0.1 o en
VIAR); una diferente para lo cual se debe introducir
la dirección IP correspondiente al servidor.
//SendMessage(hwndENVIAR, WM_
SETTEXT, 0, (long int) textoAENVIAR );
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0);
break;
default:
return DefWindowProc (hwnd, message,
wParam, lParam);
}
return 0;
}
char enviardata(HWND hwndENVIAR,
char *entrada) //FUNCION DE ENVIAR
{ En este tipo de aplicaciones, podemos direc-
cionar datos en ambas direcciones, es decir el
send(sock,entrada,strlen(entrada),0);
cliente y el servidor pueden hacer las veces
SendMessage(hwndENVIAR, WM_SET- de transmisor y de receptor. En la pantalla
TEXT, 0, (long int) “ “ ); anterior visualizamos el mensaje recibido, lo
} que transmitió la aplicación servidor.
void InsertarMenu(HWND hwnd)
{ Conclusiones.
HMENU hMenu1, hMenu2;
hMenu1 = CreateMenu(); La implementación va a depender siempre
del sistema operativo que se esté utilizando.
hMenu2 = CreateMenu();
Si el sistema es Linux se debe utilizar libre-
AppendMenu(hMenu2, MF_STRING, CM_ rías específicas, con las cuales realizar el pro-
CONECTAR, “&Conectar”); ceso. Funcionalmente el procedimiento no
AppendMenu(hMenu2, MF_STRING, CM_ sufre cambios significativos.
CERRARCONEXION, “&Cerrar Conex-
ion”); La mayoría de lenguajes de programación
AppendMenu(hMenu2, MF_SEPARATOR, permiten hacer este tipo de implementacio-
0, NULL); nes, pues poseen las librerías y funciones
AppendMenu(hMenu2, MF_STRING, CM_ con las cuales trabajar.
SALIR, “&Salir”);
En la actualidad existe una gran variedad de
AppendMenu(hMenu1, MF_STRING | MF_ aplicaciones que utilizan este tipo de arqui-
POPUP, (UINT)hMenu2, “&Menu”); tectura (cliente/servidor) para interactuar;
SetMenu (hwnd, hMenu1); pues se logran optimizar los recursos y dis-
58
58 } tribuir los procesos.

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011


HÉCTOR JULIO FÚQUENE ARDILA V Í N C U L O S
JU L I O - D I C I EM B R E D E 2 0 1 1
VOLUMEN 8 NÚMERO 2

El proceso realizado en el cliente lo podemos Se puede mejorar el programa para


considerar más sencillo que el realizado en que permita la transmisión de archi-
el servidor según se esquematiza en el si- vos, pues actualmente se transmiten
guiente diagrama.
los caracteres de forma individual.

Servidor Cliente
Referencias Bibliográficas
DEITEL, Harvey M. Cómo programar en C/
socket  socket  C++ y Java. México: Prentice Hall. 2004
DONOHOO Michael J., CALVERT, L Ken-
bind  neth. TCP/IP sockets in C bundle. Edito-
connect  rial PrenticeHall. 2009
listen  DONAHOO, Michael. TCP/IP Sockets in C:
Practical guide for programmers. Estados
Unidos: Morgan Kaufmann. 2009
accept 
FOROUNZAN Behrouz A. Transmisión de
Datos y Redes de Comunicaciones. Mc-
Trx/Rx  Trx/Rx GrawHill. 2009
KENDALL, Kenneth. Análisis y Diseño de
Sistemas. México: Prentice Hall. 2005
close  close 
MÁRQUEZ García Manuel, Unix, Progra-
mación avanzada, editorial Ra-ma. 2005
El programar la WIN-API de Windows RUMBAUGH James, Modelado y diseño
nos facilita enormemente el trabajo; orientado a objetos. Metodología OMT,
Editorial Prentice Hall. 2006
nos da la posibilidad del uso de inter-
faces estándar y permite una mayor STALLING, William. Comunicaciones y Re-
des de Computadores. Editorial Prentice-
interacción entre el usuario y la aplica-
Hall. 2000
ción; identificando plenamente los dos
extremos de la transmisión, el cliente y Fuentes Electrónicas
el servidor. http://www.winprog.org/tutorial/es/in-
dex.html
Trabajos futuros http://es.tldp.org/Universitarios/semina-
rio-2-sockets.html
El programa se puede mejorar para http://www.chuidiang.com/varios/Li-
que sea un poco más didáctico para el bros/libros.php
usuario final, de tal forma que se pue- http://www.arrakis.es/~dmrq/beej/in-
da identificar el tipo de transmisión, el dex.html
modo de transmisión y las velocidades http://www.mitecnologico.com/Main/
de transmisión utilizadas. ComunicacionClienteServidorSockets

59
59

REVISTA VÍNCULOS VOL. 8 NÚMERO 2 JULIO - DICIEMBRE DE 2011

También podría gustarte