/** * Programa Cliente de Eco para una conexion SCTP * Peer - to - Peer (Multistreams) * Similar al caso de TCP pero con multistreams * 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 #include #define PUERTO "12345" #define DIRECCION "127.0.0.1" #define MAXBUFFER 256 int main(int argc, char *argv[]) { int sd; // descriptor del socket reusable para conexiones por el mismo puerto. struct addrinfo hints, *servinfo, *p; // estructura getaddrinfo. struct addrinfo *addrs; // estructura con las direcciones de conexion. socklen_t statuslen, addrslen; // estructura para almacenar largos de datos del estatus y direccion. int res; char str[MAXBUFFER]; int one=1; char dir[32]; int out_channel, flags; struct sctp_initmsg initmsg; struct sctp_status status; struct sctp_sndrcvinfo info; if (argc > 1) strcpy(dir, argv[1]); else strcpy(dir,"127.0.0.1"); 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 NULL if ((res = getaddrinfo(DIRECCION, PUERTO, &hints, &servinfo)) != 0) { printf("getaddrinfo: %s\n", gai_strerror(res)); return -1; } if ((addrs = (addrinfo*)malloc(sizeof(struct addrinfo))) == NULL) exit(1); //reservamos el espacio de memoria del arreglo. // nos conectamos 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 } // cliente addrslen = sizeof(struct addrinfo); memcpy(addrs, &p, addrslen); memset(&initmsg, 0, sizeof(initmsg)); initmsg.sinit_max_instreams = 3; printf("Streams de entrada máximos: %i.\n", initmsg.sinit_max_instreams); initmsg.sinit_num_ostreams = 2; printf("Streams de salida: %i.\n", initmsg.sinit_num_ostreams); if (setsockopt(sd, IPPROTO_SCTP, SCTP_INITMSG, &initmsg, sizeof(initmsg))) { perror("Error setsockopt init\n"); } if (sctp_connectx(sd, p->ai_addr, 1, 0) < 0) { // 1 direccion de coneccion, la id se configurara luego // no se pudo conectar close(sd); perror("sctp_connectx"); continue; // trata otra estructura en la lista } break; // Ya esta conectado. } if (p == NULL) { // Se sale de la lista sin conexion establecida fprintf(stderr, "falló en conectar.\n"); return -1; } // listo para transmisiones entre cliente y servidor SCTP freeaddrinfo(servinfo); // eliminamos la estructura, para liberar la memoria. //fcntl(sd, F_SETFL, ~O_NONBLOCK); statuslen = sizeof(status); memset(&status, 0, statuslen); status.sstat_assoc_id = 1; // id de la asociacion. if (getsockopt(sd, IPPROTO_SCTP, SCTP_STATUS, &status, &statuslen) == -1) { perror("sctp getsockopt\n"); } printf("Se lograron establecer %d streams de entrada y %d streams de salida.\n", status.sstat_instrms, status.sstat_outstrms); out_channel = 1; // se elige el canal 1 para el envio de datos. if (out_channel >= status.sstat_outstrms) perror("Error, el canal de salida no es valido"); printf("inicia rutina de echo:\n"); memset(&info, 0, sizeof(info)); info.sinfo_stream = out_channel; // elegimos el canal para enviar. while ((gets(str)) != NULL) { if (strcmp(str,"BYE") == 0) break; // if ((sctp_sendmsg(sd, str, strlen(str), (struct sockaddr*)&addrs, addrslen, 0, 0, 1, 0, 0)) < 0) { //enviamos los datos por el canal indicado. if ((sctp_send(sd, str, strlen(str), &info, 0)) < 0) { //enviamos los datos por el canal indicado. // if ((send(sd, str, MAXBUFFER, 0)) < 0) { printf("Error, conexión perdida.\n"); exit(-1); } printf("Cliente SCTP: %s\n", str); sprintf(str, " "); while ((sctp_recvmsg(sd, str, MAXBUFFER, (struct sockaddr*)&addrs, &addrslen, &info, &flags)) <1); // recv(sd, str, MAXBUFFER, 0); printf("Servidor SCTP: %s\n", str); } info.sinfo_flags = SCTP_EOF; sctp_send(sd, NULL, 0, &info, 0); close(sd); return 0; }