Bueno, al final pude recibir sockets, pero quise ir un poco mas alla y usar la funcion select.
Estoy abriendo el server y dos clientes.
Estoy teniendo dos problemas:
1) Sólo me reconoce una conexión (puse que me imprima en pantalla cuando haya una nueva conexión). De hecho ambos clientes se conectan porque ninguno me tira el error de que no se pudo conectar, pero sólo llega el mensaje del cliente que abrí primero.
2) No me imprime más de 8 caracteres del buffer...
3) Cuando el server recibe un mensaje, lo recibe y se cierra (se supone que no lo tendria que hacer, esta todo en un ciclo infinito)
Del 1 seguro me estoy comiendo algo en el código, pero en el 2 no tengo ni la más mínima idea que puede ser.
Server
/*
============================================================================
Name : serverMulti.c
Description : Server Multi Conexiones
============================================================================
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#define MAXCLIENTES 10
#define MIN 50
#define PORT 38432
void checkError(int, char*);
int main(void) {
struct sockaddr_in direccionServer;
struct sockaddr_in direccionCliente;
char *buffer = NULL;
int yes = 1;
int socketServer, socketCliente;
int binder, reutilizer, listening, receive, sender; /*variables que toman los valores que devuelven las respectivas
funciones para chequear errores*/
unsigned int addrlen;
int bytesRecibidos = 0, bufferSize = MIN;
int i = 0;
int socketsDeClientes[MAXCLIENTES]; /*Array que alberga los descriptores de los clientes que se nos conecten*/
fd_set read_descriptors; /*Es una estructura que va a guardar los descriptores que esten para leer*/
int maxDescriptores = 0; /*Indica la cantidad maxima de descriptores hasta el momento*/
int posUltimoCliente = 0;
socketServer = socket(AF_INET, SOCK_STREAM, 0);
checkError(socketServer, "SOCKET\n");
reutilizer = setsockopt(socketServer, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
checkError(reutilizer, "REUTILIZAR PUERTO\n");
direccionServer.sin_family = AF_INET;
direccionServer.sin_port = htons(PORT);
direccionServer.sin_addr.s_addr = htonl(INADDR_ANY); //mi propia direccion IP
memset(&(direccionServer.sin_zero), '\0', 8);
binder = bind(socketServer, (struct sockaddr *)&direccionServer, sizeof(direccionServer));
checkError(binder, "BIND\n");
maxDescriptores = socketServer; /*el socketServer va a ser el descriptor de valor maximo por el momento*/
bzero(socketsDeClientes, MAXCLIENTES);
/*pongo el socket a escuchar nuevas conexiones*/
listening = listen(socketServer, MAXCLIENTES);
checkError(listening, "LISTENING\n");
/*meto el descriptor del socket del server en read_descriptores*/
FD_ZERO(&read_descriptors); /*vacio read_descriptors primero*/
FD_SET(socketServer, &read_descriptors); /*Meto el socket del servidor en la estructura*/
while(1){
select(maxDescriptores + 1, &read_descriptors, NULL, NULL, NULL); /*hago select*/
/*se trata el server, se entra aca si se recibe una nueva conexion*/
if (FD_ISSET(socketServer, &read_descriptors)){
puts("AVISO: Nueva conexion.");
addrlen = sizeof(direccionCliente);
socketCliente = accept(socketServer, (struct sockaddr *)&direccionCliente, &addrlen);
checkError(socketCliente, "ACCEPT\n");
//agrego el descriptor al array de clientes y luego lo setteo en read_descriptors
socketsDeClientes[posUltimoCliente] = socketCliente;
FD_SET(socketCliente, &read_descriptors);
//asigno el valor del descriptor del cliente nuevo al de maxDescriptores si es mayor a este
if (socketCliente>maxDescriptores) maxDescriptores = socketCliente;
posUltimoCliente++;
}
/*se tratan los sockets clientes*/
for (i = 0; (i < MAXCLIENTES); i++){
if (FD_ISSET(socketsDeClientes[i], &read_descriptors)){
/*uno de los clientes envio informacion, se tratan aca*/
/*agrando el buffer hasta que sea lo suficientemente grande como para contener el mensaje en su totalidad*/
do{
bufferSize += 10;
if (buffer == NULL){
buffer = malloc(MIN);
bzero(buffer, MIN);
} else {
buffer = realloc(buffer, bufferSize);
bzero(buffer, bufferSize);
}
bytesRecibidos = recv(socketsDeClientes[i], buffer, sizeof(buffer), MSG_PEEK);
} while (bufferSize < bytesRecibidos);
/*ahora si recibo el paquete completo*/
receive = recv(socketsDeClientes[i], buffer, sizeof(buffer), 0);
checkError(receive, "RECV\n");
printf("Cliente %i: %s\n", i , buffer);
free(buffer);
buffer = NULL;
sender = send(socketsDeClientes[i], "Mensaje enviado correctamente.", strlen("Mensaje enviado correctamente."), 0);
checkError(sender, "SEND\n");
}
}
}
/*cierres*/
for (i = 0; i <= posUltimoCliente; i++){
close(socketsDeClientes[i]);
}
close(socketServer);
free(buffer);
return EXIT_SUCCESS;
}
void checkError(int valor, char *mensajeError){
if (valor == -1){
perror(mensajeError);
exit(1);
}
}
Cliente
/*
============================================================================
Name : client.c
Description : CLIENT
============================================================================
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
#include <netdb.h>
#define BACKLOG 10
#define MIN 50
#define PORT 38432
/*
* Estructura sockaddr_in
*
* Reemplaza a sockaddr, generalmente se lo usa casteado: (struct sockaddr *)VariableDeTipoSockaddr_in
*
* Nombre de Valor: descripcion: que se le asigna
* sin_family: familia de direcciones: AF_INET
* sin_port: numero de puerto: htons(NUMPUERTO)
* sin_addr.s_addr: direccion de internet: inet_addr("direccion IP") o htonl(INADDR_ANY) si uso la de mi PC
* sin_zero[8]: relleno para preservar el tamanho: inicializar con memset(puntero, valor, bytes)
*
*/
void checkError(int, char*);
int main(void) {
int sockfd, s, r;
char *buffer = NULL, hostname[40];
struct hostent *server;
struct sockaddr_in direccionServer;
int bytesRecibidos = 0, bufferSize = MIN;
char mensaje[300];
/*obtengo el hostname*/
gethostname(hostname, sizeof hostname);
/*setteo descriptor del socket al que me voy a conectar*/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
checkError(sockfd, "SOCKET\n");
server = gethostbyname(hostname);
if (server == NULL) {
perror("gethostbyname");
exit(1);
}
/*setteo la direccion del server*/
direccionServer.sin_family = AF_INET;
direccionServer.sin_port = htons(PORT);
bcopy((char *)server->h_addr,(char *)&direccionServer.sin_addr.s_addr,server->h_length);
memset(&(direccionServer.sin_zero), '\0', 8);
/*conecto a server*/
checkError(connect(sockfd, (struct sockaddr *)&direccionServer, sizeof(direccionServer)), "CONNECT\n");
/*mando un mensaje*/
puts("Manda un mensaje:");
scanf("%s", mensaje);
s = send(sockfd, mensaje, strlen(mensaje) + 1, 0);
checkError(s, "SEND\n");
/*agrando el buffer hasta que sea lo suficientemente grande como para contener todo el paquete*/
do{
bufferSize += 10;
if (buffer == NULL){
buffer = malloc(MIN);
bzero(buffer, MIN);
} else {
buffer = realloc(buffer, bufferSize);
//bzero(buffer, bufferSize);
}
bytesRecibidos = recv(sockfd, buffer, sizeof(buffer), MSG_PEEK);
} while (bufferSize < bytesRecibidos);
/*ahora si recibo el mensaje*/
r = recv(sockfd, buffer, sizeof(buffer), 0);
checkError(r, "RECV\n");
printf("Server: %s\n", buffer);
/*cierres*/
free(buffer);
close(sockfd);
return EXIT_SUCCESS;
}
void checkError(int valor, char *mensajeError){
if (valor == -1){
perror(mensajeError);
exit(1);
}
}