Título: Haciendo un chat por sockets
Publicado por: ipmicrobious en 3 Diciembre 2016, 14:22 pm
El principal problema que nos surge es que no logro hacer un sendto y un receivefrom del socket declarados, el valor de result nos sale de -1, dando error en el sendto por no enviarse correctamente. ¿Entendéis a qué se debe el fallo?, me he quedado trabado... Por aquí tenéis el main... #include "socket.hpp"
sockaddr_in make_ip_address(const std::string& ip_address, int port){
uint32_t ip_b = atoi(ip_address.c_str());
sockaddr_in local_address{}; // Porque se recomienda inicializar a 0 local_address.sin_family = AF_INET; local_address.sin_addr.s_addr = htonl(ip_b); //Para escuchar por todas las direcciones IP de nuestra máquina. local_address.sin_port = htons(port); // Escogemos 0 para que el sistema operativo asigne un puerto cualquiera que esté disponible
/* Hemos hecho uso de htonl() y htons() para convertir enteros de 32 o de 16 bits [como el número de puerto] del orden de bytes usado por nuestra CPU al que espera la interfaz de comunicaciones*/
return local_address;
}
int main(int argc, char* argv[]){
//Mensaje del socket local hacia el remoto - Prueba string message_text("¡Hola, mundo!");
//Dirección del socket local string direccion_ip = "0.0.0.0"; int puerto = 0; sockaddr_in local_address = make_ip_address(direccion_ip, puerto); Socket s(local_address);
// Dirección del socket remoto string direccion_ip_remota = "0.0.0.0"; int puerto_remoto = 0; sockaddr_in remote_address = make_ip_address(direccion_ip_remota, puerto_remoto); Socket s2(remote_address);
//A continuación vamos a copiar el mensaje almacenado en nuestro string hacia la clase message_text.copy(s.message.text, sizeof(s.message.text) - 1, 0); s.send_to(s.message, remote_address); return 0;
}
Os paso también el cpp de la clase Socket que estoy creando, justo en la función send_to es donde se almacena el valor de result que da -1 y por consiguiente error... #include "socket.hpp"
Socket::Socket(const sockaddr_in& address){
/*Creación del socket || Devuelve un descriptor de archivo con el que identificar al socket en cuestión de futuras operaciones que se hagan sobre él
socket(domain, type, protocol)
domain -> AF_INET | Porque estamos interesados en la tecnología TCP/IP
type -> SOCK_DGRAM |Nuestro tipo de socket nos interesa que sea de tipo datagram
protocol -> 0 | Protocolo específico que queremos que sea utilizado internamente por el socket para el envío de datos. En nuestro caso con la familia IP (AF_INET) con sockets tipo datagram (SOCK_DGRAM) sólo admite UDP como protocolo, por lo que este argumento debe ser 0 */
fd = socket(AF_INET, SOCK_DGRAM, 0); check_socket_ini(fd); int result = bind(fd, reinterpret_cast<const sockaddr*>(&address), sizeof(address)); check_socket_bind(result);
/* Cuando un socket es creado a través de socket(), existe en un ambiente (adress family), pero no tiene una dirección asignada. Una dirección se asigna a un socket que acabamos de crear mediante la llamada al sistema bind()
int bind(int sockfd, const sockaddr* addr, socklen_t addrlen)
bind() no acepta una dirección IP y un número de puerto como parámetros. En su lugar recibe una estructura sockaddr genérica que puede dar cabida a cualquier tipo de dirección. Por ejemplo, para AF_INET se utiliza la estructura sockaddr_in declarada en <netinet/ip.h>.
struct sockaddr_in { sa_family_t sin_family; // dominio: AF_INET in_port_t sin_port; // número de puerto en // orden de bytes de la red. struct in_addr sin_addr; // dirección de internet };
// Dirección de internet struct in_addr { uint32_t s_addr; // dirección en orden de bytes // de la red. }; */
}
Socket::~Socket(){
}
int Socket::check_socket_ini(int fd){
if (fd < 0){ std::cerr << "No se pudo crear el socket: " << //std::cerr no tiene un buffer, generalmente se usa para errores std::strerror(errno) << '\n'; return 3; // Error. Termina el programa siempre con un valor > 0 || (return 3 - El sistema no puede encontrar la ruta especificada) } }
int Socket::check_socket_bind(int result){
if (result < 0){ std::cerr << "Falló bind: " << std::strerror(errno) << '\n'; return 5; // Error. Termina el programa siempre con un valor > 0 || return 5 - Acceso denegado } }
void Socket::send_to(const Message& message, const sockaddr_in& address){
int result = sendto(fd, &message, sizeof(message), 0, reinterpret_cast<const sockaddr*>(&address), sizeof(address)); check_message_send(result); cout << result << endl;
}
void Socket::receive_from(Message& message, sockaddr_in& address){
// int result = recvfrom(fd, &message, sizeof(message), 0, reinterpret_cast<sockaddr*>(&remote_address), &src_len);
}
int Socket::check_message_send(int result){
if (result < 0) { std::cerr << "Falló sendto: " << std::strerror(errno) << '\n'; return 6; } } Gracias de antemano, es una conexión tipo UDP. Estoy tratando de hacer el cliente y el servidor en el mismo fichero, no sé si es lo más correcto o si es posible...
Título: Re: Haciendo un chat por sockets
Publicado por: ivancea96 en 3 Diciembre 2016, 16:03 pm
Si el sendto retorna SOCKET_ERROR (-1), utiliza la función WSAGetLastError (https://msdn.microsoft.com/en-us/library/windows/desktop/ms741580(v=vs.85).aspx) Para ver qué error hubo. Aquí ves qué significa cada valor devuelto por WSAGetLastError: https://msdn.microsoft.com/en-us/library/windows/desktop/ms740148(v=vs.85).aspx (https://msdn.microsoft.com/en-us/library/windows/desktop/ms740148(v=vs.85).aspx)
|