I have a program which prints the content of a file which I send:
struct addrinfo hints;
struct addrinfo *serverInfo;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
getaddrinfo(NULL, PUERTO, &hints, &serverInfo);
//socket para escuchar
int listenningSocket;
listenningSocket = socket(serverInfo->ai_family, serverInfo->ai_socktype, serverInfo->ai_protocol);
bind(listenningSocket,serverInfo->ai_addr, serverInfo->ai_addrlen);
freeaddrinfo(serverInfo);
listen(listenningSocket, BACKLOG);
struct sockaddr_in addr;
socklen_t addrlen = sizeof(addr);
int socketCliente = accept(listenningSocket, (struct sockaddr *) &addr, &addrlen);
char package[PACKAGESIZE];
int status = 1;
printf("\nCliente conectado. Esperando mensajes:\n");
printf("\nEl contenido del script es: \n");
while (status != 0) {
status = recv(socketCliente, (void*) package, PACKAGESIZE, 0);
if (status != 0) printf("%s", package);
}
close(socketCliente);
close(listenningSocket);
But I want this program listen for others things I want to print. So I need to cycle the socket, the listening of the socket. I understand I need the select() function, but I don't know how to use it for my code.
You need to call
select()(or better,epoll()) in a loop, where you pass itsreadfdsparameter anfd_setcontaining the listening socket descriptor and all connected client socket descriptors. Whenselect()exits, it will tell you which sockets have pending readable data on them.If the listening socket has pending data to read, call
accept()on it, and if successful then add the returned socket descriptor to a tracking list somewhere so that you can include it in subsequent calls toselect().If any other sockets have pending data to read, call
recv()on them and act on their data as needed. Ifrecv()returns -1 or 0 on any given socket,close()that socket descriptor and remove it from your tracking list so you omit it in subsequent calls toselect().That being said, all of your socket calls are missing adequate error handling. Any of them can fail, and you wouldn't know This is especially important for
recv()so you can properly detect and cleanup any disconnected/lost client connections.Also, you are assuming that
recv()always returns null-terminated strings, but that is simply not true. A client may send a null-terminated string, butrecv()is not guaranteed to read an entire null-terminated string in one read. You have to callrecv()in a loop, buffering any received data in between, until you actually receive the null terminator, THEN proceed with processing the completed string.Try something more like this (pseudo-code for you to fill in the implementation details of the client tracking list as desired):