/** * Programa Servidor de Eco para una conexion SCTP * Peer - to - Peer (multistreams) * Similar al caso de TCP pero con Multistream * Programado por Benjamin Ginouves * Para el proyecto de fin de ramo ELO330, 2s2010. */ #include #include #include #include #include // requiere instalar el paquete correspondiente y compilar con la libreria sctp #include #include #include //#include #include //#include //#include //#include #define PUERTO "12345" #define MAXBUFFER 256 int main(int argc, char *argv[]) { int sd; // descriptor del socket reusable para conexiones entrantes por el mismo puerto. int s; // descriptor socket conexion struct addrinfo hints, *servinfo, *p; // estructura getaddrinfo struct sockaddr_storage addrfrom; // estructura para alojar datos de conexion para la recepcion y envio al cliente SCTP. socklen_t addrfromlen, statuslen; // estructura para almacenar largos de datos del cliente SCTP y su estatus. int res, n; char str[MAXBUFFER]; int one=1; struct sctp_initmsg initmsg; struct sctp_status status; memset(&hints, 0, sizeof(hints)); // se inicia la estructura en cero hints.ai_family = AF_UNSPEC; // para IPv4 o IPv6 hints.ai_socktype = SOCK_STREAM; // tipo de transmision de datos hints.ai_protocol = IPPROTO_SCTP; // definimos el protocolo SCTP hints.ai_flags = AI_PASSIVE; // localhost, con addr en NULL if ((res = getaddrinfo(NULL, PUERTO, &hints, &servinfo)) != 0) { printf("getaddrinfo: %s\n", gai_strerror(res)); return -1; } // hacemos bind a la lista de direcciones que corresponden a la llamada de getaddrinfo for (p = servinfo; p != NULL; p = p->ai_next) { if ((sd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { // no se pudo abrir el socket perror("socket"); continue; // trata otra estructura en la lista } if (setsockopt(sd,SOL_SOCKET,SO_REUSEADDR,(char *) &one,sizeof(one)) == -1 ) { perror("setsockopt"); continue; // trata otra estructura en la lista } // servidor if (bind(sd, p->ai_addr, p->ai_addrlen) == -1) { // no se pudo close(sd); perror("sctp bind"); continue; // trata otra estructura en la lista } break; // bind listo. } if (p == NULL) { // Se sale de la lista sin bind establecido fprintf(stderr, "fallo en bind sctp.\n"); return -1; } freeaddrinfo(servinfo); // eliminamos la estructura, para liberar la memoria, no se utilizara luego memset(&initmsg, 0, sizeof(initmsg)); initmsg.sinit_max_instreams = 2; printf("Streams de entrada máximos: %d.\n", initmsg.sinit_max_instreams); initmsg.sinit_num_ostreams = 3; printf("Streams de salida: %d.\n", initmsg.sinit_num_ostreams); if (setsockopt(sd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg))) { perror("Error en setsockop\n"); } // espera una conexion del cliente listen(sd, 2); for (;;) { printf("accepta conexiones...\n"); addrfromlen = sizeof(addrfrom); if ((s = accept(sd, (struct sockaddr *)&addrfrom, &addrfromlen)) == -1) { perror("accept sctp"); continue; } memset(&status, 0, sizeof(status)); statuslen = sizeof(status); if (getsockopt(s, IPPROTO_SCTP, SCTP_STATUS, &status, &statuslen) == -1) { perror("getsockopt"); } printf("Se estabecieron %d streams de entrada y %d streams de salida.\n", status.sstat_instrms, status.sstat_outstrms); printf("Inicia Echo: \n"); while ((n = recv(s, str, MAXBUFFER, 0)) > 0) { printf("Cliente: %s\n", str); if ((send(s, str, MAXBUFFER, 0)) < 0) { printf("Error, conexión perdida.\n"); exit(-1); } } close(s); } return 0; }