Cómo aprender a programar la red de Windows
Aprendizaje imprescindible para principiantes: una introducción clásica a la programación de redes de Windows
Autor: huyoo
Para un principiante en la programación de redes de Windows, el siguiente método es una Introducción clásica.
Se recomienda a los principiantes que no utilicen las clases proporcionadas por MFC, sino que utilicen la API de Windows para crear un servidor y un cliente simples. Esto les ayudará a comprender el mecanismo de programación del socket.
Para simplificar, la aplicación se basa en los cuadros de diálogo estándar de MFC.
Winsock se implementa utilizando la API de WINDOWS:
(1) Hay dos subprocesos en el lado del servidor:
Subproceso principal: debe escribir la siguiente función para implementarlo
#define NETWORK_EVENT USER_MESSAGE 100 file://Definir eventos de red
sockaddr_in clientaddr file://Almacenar temporalmente la dirección IP del cliente
archivo ://Defina su propia función de mapeo de mensajes, asigna el evento de red definido anteriormente a la función de procesamiento
file://OnNetEvent es la función de procesamiento de eventos de red, que se define a continuación
ON_MESSAGE(NETWORK_EVENT, OnNetEvent);
Llame a la siguiente subfunción para inicializar la red en la función de inicialización en su cuadro de diálogo
Archivo BOOL InitNetwork(): //Inicializar la red
{
p>
archivo: //Inicializar protocolo TCP
BOOL ret = WSAStartup(MAKEWORD(2, 2), & wsaData);
if(ret != 0)
{
MessageBox("¡Error al inicializar el socket!");
return FALSE;
}
archivo://Crear socket del lado del servidor
SOCKET serverSocket
= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(serverSocket == INVALID_SOCKET)
{
MessageBox("¡Error al crear el socket!");
closesocket(m_Socket);
WSACleanup( );
devuelve FALSO
}
archivo: //Enlazar a un puerto local
sockaddr_in localaddr;
p>
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(1688); sin_addr.s_addr = 0;
if (bind(serverSocket, (const struct sockaddr*)&localaddr,
sizeof(sockaddr)) == SOCKET_ERROR)
{
MessageBox("¡Error en la determinación de la dirección de enlace!");
closesocket(m_Socket);
WSACleanup(); FALSE;
}
p>
archivo: //Registra eventos asincrónicos de red, m_hWnd es el identificador del cuadro de diálogo principal o ventana principal de la aplicación
WSAAsyncSelect(serverSocket, m_hWnd, NETWORK_EVENT,
FD_ACCEPT | FD_CLOSE | FD_READ | FD_WRITE );
p>
listen(serverSocket, 5); file://Establecer modo de escucha
return TRUE
}
file: //Definición de red; función de respuesta al evento
void OnNetEvent(WPARAM wParam, LPARAM lParam)
{
file: //Llame a la función API para obtener el tipo de evento de red p>
{ p>
int iEvent = WSAGETSELECTEVENT(lParam);
file: //Obtiene el socket del cliente que emitió este evento
SOCKET pSock = (SOCKET )wParam;
switch(iEvent)
{
caso FD_ACCEPT: archivo://solicitud de conexión del cliente
{
OnAccept();
romper;
}
caso FD_CLOSE: archivo://Evento de desconexión del cliente:
{
OnClose(pSock);
break;
}
case FD_READ: file://Evento de llegada de paquete de red p>
p>
{
OnReceive(pSock);
romper
}
caso FD_WRITE: file://enviar eventos de datos de red
{
OnSend(pSock
break
}
<; p>predeterminado: break}
}
void OnAccept(SOCET pSock) file: //Respuesta a la función de solicitud de conexión del cliente
{ p>
int len = sizeof(sockaddr);
file: //Llama a la función API, acepta la conexión y devuelve un nuevo socket
file: //También se puede obtener la dirección IP del cliente
SOCKET clientSocket = Accept(serverSocket,
(struct sockaddr*)amp; clientaddr, amp;len); /p>
archivo: //Registra eventos asincrónicos para el nuevo socket, tenga en cuenta que no hay ningún evento de aceptación
if(WSAAsyncSelect(clientSocket, m_hWnd, IP_EVENT,
FD_CLOSE | FD_READ | FD_WRITE) == SOCKET_ERROR)
p>{
MessageBox("¡Error al registrar el evento asincrónico!");
}
archivo: //Escribe tu propia función para guardar la información relevante de este cliente: socket,
//dirección IP, hora de inicio de sesión
saveClientSocket(clientSocket, clientAddr, currentTimer);
}
void OnClose(SOCET pSock)
<p>{
file: //Función autoescrita, finaliza la comunicación con el cliente correspondiente, libera los recursos correspondientes y realiza el procesamiento correspondiente
endClientSocket(pSock
}
void OnSend(SOCET pSock)
{
file: //Función autoescrita para realizar algún preprocesamiento al enviar datos al cliente
handleOnSend(pSock);
}
void OnReceive(SOCET pSock)
{
recv (...); archivo: //Llame a la función API para leer el paquete de datos en el búfer de la red
archivo: //Función autoescrita para conectar este paquete de datos al cliente que envió estos datos
p>
archivo: //clientSocket se encapsula en un mensaje de red
buildNetMsg(...
archivo: //Self-); función escrita para colocar este mensaje de red en una cola de mensajes, es procesado por el hilo de trabajo
saveNetMsg(...);
SetEvent(...); // Activa el hilo de trabajo con el objeto de evento
p>}
Después de que el cliente inicia sesión, envía inmediatamente el nombre de su computadora al servidor. lo guarda. De esta manera, el servidor puede mostrar toda la información del cliente en línea, incluido: nombre de la computadora del cliente, dirección IP, hora de inicio de sesión, etc.
Nota: El cliente no tiene la función OnAccept(), pero sí la función OnConnect().
Subproceso de trabajo:
Crea e inicia un subproceso de trabajo cuando se inicializa tu aplicación
AfxBeginThread(WorkThread, this, THREAD_PRIORITY_NORMAL
); file://este puede ser el identificador del cuadro de diálogo principal o de la ventana principal de la aplicación
UINT WorkThread(LPVOID pParam)
{
while(1)
{
file: //Esperar a que lleguen múltiples eventos
int ret = WaitForMultipleObject(...);
switch; (ret)
{
case OBJECT_0:
{
if(bNewNetMsg) file://Ver cola de mensajes de red ¿Existe? ¿Un nuevo mensaje de red?
{
readNetMsg(...); file: //Si hay un nuevo mensaje de red, léelo en voz alta
handleNetMsg. (...); file://procesar este mensaje de red
}
break;
}
case OBJECT_0 1:
{
archivo: //Salir del procesamiento
break;
}
predeterminado: break;
}
return 0;
}
El cliente es de un solo subproceso. Al iniciar sesión en el servidor, utilice la conexión. función () para enviar una solicitud de conexión;
El cliente no tiene la función OnAccept(), pero tiene la función OnConnect().
Realizar preprocesamiento al enviar solicitudes de conexión en la función OnConnect()
Responder y procesar datos de red en la función OnReceive()
En OnClose (); función para responder al evento de apagado del servidor
Realice un preprocesamiento al enviar datos en la función OnSend()
Si también desea lograr la comunicación en línea entre clientes Para la comunicación (así; -llamada sala de chat), también puede crear un conjunto de modelos de multidifusión LAN multipunto a multipunto basado en el protocolo UDP en el cliente. Cuando charle con usted más tarde, primero puede implementar el programa anterior.
El modelo asincrónico de E/S anterior se basa en el mecanismo de mensajes de Windows. Además, también se puede utilizar el modelo de evento, el modelo de superposición o el modelo de puerto de finalización. que consulte la Guía de programación de redes de Windows y libros similares.
Si domina el mecanismo anterior, debe tener cierta comprensión del mecanismo Winsock para programar programas de red. A continuación, podrá realizar una programación más interesante, que no solo puede transmitir datos ordinarios en Internet. , pero también puede transmitir datos de voz y video. También puede crear una sala de chat usted mismo y compartir sus resultados con sus compañeros de clase en la LAN del laboratorio.