Chat c++ sockets windows duda

Iniciado por patilanz, 5 Mayo 2014, 21:09 PM

0 Miembros y 2 Visitantes están viendo este tema.

patilanz

Hola recién empiezo con los sockets y solo en windows y quiero intentar a hacer un chat pero tengo 2 problemas.
Quiero que el chat funcione con un server al que llegan mensajes de varios usuarios y luego el server envie el mensaje para su destino. Pero el problema aquí son los usuarios ya que cuando acepta un mensaje para de aceptar mas. No se como hacer lo multiarea.

Luego el otro problema es que quiero que los mensajes al cliente van llegando pero a su vez este pueda escribir cuando quiera de modo que al aceptar los mensajes del servidor no influya a funciones para coger teclas del teclado, necesito que sean dos procesos distintos.

Alguien me puede ayudar con algun tutorial o ayuda pls  :D

x64core

Cita de: patilanz en  5 Mayo 2014, 21:09 PM
Hola recién empiezo con los sockets y solo en windows y quiero intentar a hacer un chat pero tengo 2 problemas.
Quiero que el chat funcione con un server al que llegan mensajes de varios usuarios y luego el server envie el mensaje para su destino. Pero el problema aquí son los usuarios ya que cuando acepta un mensaje para de aceptar mas. No se como hacer lo multiarea.

Luego el otro problema es que quiero que los mensajes al cliente van llegando pero a su vez este pueda escribir cuando quiera de modo que al aceptar los mensajes del servidor no influya a funciones para coger teclas del teclado, necesito que sean dos procesos distintos.

Alguien me puede ayudar con algun tutorial o ayuda pls  :D
Yo no entendí como tienes pensado que los programas/Usuarios funcionarian junto con el server.
Pero ¿cual es el problema? cómo crear aplicaciónes multitarea o cómo es la estructura en general de los programas multitarea?



patilanz

Yo creo que necesito aprender como funcionan y se crean las aplicaciones multiarea para crear el chat pero no estoy seguro.En estos dos casos es necesario o se puede hacer de otra forma? :

1 - El programa cliente al empezar pide un nombre de usuario que envía hasta el server, hasta aquí bien. Luego tiene que empezar a escuchar al server los mensajes entrantes y poder cambiar el texto en la consola pero a su vez tiene que poder escuchar lo que escribe el usuario pero conjuntamente se bloquean.

2 - El server solo puede atender a un usuario a la vez como lo hago para que atienda a mas?

Ahora me he explicado bien así?

x64core

Cita de: patilanz en  6 Mayo 2014, 07:21 AM
Yo creo que necesito aprender como funcionan y se crean las aplicaciones multiarea para crear el chat pero no estoy seguro.En estos dos casos es necesario o se puede hacer de otra forma? :
Más bien depende del diseño de tu aplicación. Te puedo recomendar este libro buena introducción con ejemplos, explica como crear aplicaciones multihilos.

eferion

Lo que sucede, creo yo, es que estás definiendo las conexiones como bloqueantes. Al ser una conexión bloqueante, si tu código llama a la función recv o recvfrom el hilo se quedará congelado dentro de la función hasta que recibas algo.

Para solucionar esto tienes dos opciones:

* Hacer la aplicación multihilo y crear un hilo nuevo para cada cliente.

* Hacer las conexiones no bloqueantes.

Yo te voy a comentar brevemente la segunda solución, para la primera el hecho de trabajar con sockets es casi irrelevante.

Para definir una conexión como no bloqueante tienes que hacer uso de la función fcntl, cuyo prototipo aparece a continuación:


#include <fcntl.h>

int fcntl(int fd, int cmd, int arg );


El primer parámetro es el descriptor ( un socket, un archivo... lo que corresponda. En tu caso el socket ).
El segundo parámetro permite indicar el sentido de la operación, lectura o escritura.
El tercer parámetro se usa en la escritura y permite modificar ciertos parámetros del desriptor.

En nuestro caso concreto, queremos hacer una operación de escritura ( vamos, modificar el comportamiento del descriptor ) y lo que queremos modificar es el comportamiento bloqueante.

Esto se consigue con la siguiente línea:


if ( fcntl( socket, F_SETFL, O_NONBLOCK ) < 0 )
{
  // error
}


Una vez configurado el socket, si intentas realizar una operación de lectura y no hay datos para leer, el hilo de ejecución no se quedará esperando datos, sino que saldrá de la función indicándote que no ha leído absolutamente nada.

Esta circunstancia la puedes controlar así:


int data_length = recv ( socket, buffer, LENGTH_BUFFER, 0 );

if ( data_length > 0 )
{
  // Se han recibido datos
}
else if ( data_length == 0 )
{
  // No hay datos pendientes
}
else if ( data_length == SOCKET_ERROR )
{
  // Error
}

x64core


eferion

#6
--

x64core

Cita de: eferion en  6 Mayo 2014, 08:36 AM
Lo se... pero patilanz ha dicho que está en Windows
precisamente. ¿Configurando sockets con fcntl en Windows?

eferion

#8
La verdad es que hace como 6 años que no toco mucho el tema de sockets al nivel de conexiones concurrentes... pero creo recordar que el mecanismo era el mismo... voy a revisar un poco el tema por si estoy equivocado.

Cierto, estaba equivocado:


#include <winsock2.h>
#include <stdio.h>

#pragma comment(lib, "Ws2_32.lib")

void main()
{
//-------------------------
// Initialize Winsock
WSADATA wsaData;
int iResult;
u_long iMode = 0;

iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != NO_ERROR)
  printf("Error at WSAStartup()\n");

//-------------------------
// Create a SOCKET object.
SOCKET m_socket;
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_socket == INVALID_SOCKET) {
  printf("Error at socket(): %ld\n", WSAGetLastError());
  WSACleanup();
  return;
}

//-------------------------
// Set the socket I/O mode: In this case FIONBIO
// enables or disables the blocking mode for the
// socket based on the numerical value of iMode.
// If iMode = 0, blocking is enabled;
// If iMode != 0, non-blocking mode is enabled.

iResult = ioctlsocket(m_socket, FIONBIO, &iMode);
if (iResult != NO_ERROR)
  printf("ioctlsocket failed with error: %ld\n", iResult);
 

}


Código sacado de http://msdn.microsoft.com/en-us/library/windows/desktop/ms738573(v=vs.85).aspx