I am trying to get a server (SENSORSERVER) and client(CGI) to communicate using the send() function. The first loop round the SENSORSERVER sends the string "Hello world" to the CGI correctly, but on the second loop around the while loop, the CGI does not receive properly on the recv function.
SENSORSERVER Code
int main() {
pthread_mutex_init(&mutex, NULL);
int welcomeSocket, newSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
//pthread_create(&t0, NULL ,background(),(void *)"");
//pthread_detach(t0);
//int pthread_join();
pid = fork();
if(pid == -1){
printf("failed to fork");
}
if(pid == 0){
pthread_create(&t0, NULL, background(), (void*)"");
pthread_detach(t0);
} else {
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
while(1){
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket, 0) == 0)
printf("Listening\n");
else
printf("Error\n");
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
/*---- Send message to the socket of the incoming connection ----*/
int er = pthread_mutex_trylock(&mutex);
if (er == 0)
{
strcpy(buffer,"Hello World\n");
send(newSocket, buffer, sizeof(buffer), 0);
close(newSocket);
close(welcomeSocket);
pthread_mutex_unlock(&mutex);
}
}
}
return EXIT_SUCCESS;
}
And the CGI client code
char buf[1024];
char buf2[2024];
int main(void) {
int clientSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Connect the socket to the server using the address struct ----*/
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
/*---- Read the message from the server into the buffer ----*/
int er;
er = recv(clientSocket, buffer, sizeof(buffer), 0);
/*---- Print the received message ----*/
printf("Data received: %s",buffer);
//close(clientSocket);
puts("<p>Hello <b>CGI</b</p>");
puts("</BODY>");
puts("</HTML>");
return EXIT_SUCCESS;
}
The SENSORSERVER will get to the accept() function, then when CGI gets to the receive it will carry on and continue and everything seems fine. However I need the CGI to be able to be called again and again while the SENSORSERVER is running and for the server to send the client the message. It only sends it once!
First loop round output -
Data received: Hello World
<p>Hello <b>CGI</b</p>
</BODY>
</HTML>
logout
Second loop round -
Data received:
<p>Hello <b>CGI</b</p>
</BODY>
</HTML>
logout
Can anyone see where the problem is?
The problem is that your server only accepts a single connection (the single accept call), and then after sending the message it exits. So the second client run will get a connection failure (there's noone listening on the socket anymore) and print the blank message (as you ignore the error code).
If you want the server to be able to handle multiple connections, you need to have the accept call in a loop. How exactly you want to do that depends on how you want to handle the connections. The simplest would be to send the message, close the accepted connection, and loop:
while (1) { /* infinite loop */
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
if (newSocket < 0) {
perror("accept");
break; }
/*---- Send message to the socket of the incoming connection ----*/
int er = pthread_mutex_trylock(&mutex);
if (er == 0) {
strcpy(buffer,"Hello World\n");
send(newSocket, buffer, sizeof(buffer), 0);
close(newSocket);
pthread_mutex_unlock(&mutex);
} else {
/* mutex lock failed (busy?) -- need to do something */
strcpy(buffer,"Error occurred\n");
send(newSocket, buffer, sizeof(buffer), 0);
close(newSocket);
}
}
close(welcomeSocket);
If you want to do anything more complex with the incoming connection, you might want to fork a process or thread to handle it, rather than doing in the loop directly, as a second connection cannot be accepted until after the first one has been handled, and the loop returns to the accept call.
Related
I am implementing a server/client app for educational purposes. My server opens a socket and polls it for connections. If a connection is available it accepts it and sends some data over. Then it waits for input and sends some data back again.
When implementing the client side, I tried writing to the socket right away, but that did not work. I had to receive first what the server told me and then send it some data. Then wait to receive again.
This does not seem a good solution and since this is an educational project I was wondering how I would go about making it abstract (i.e. not care about how many times the server would send me something and I would send it something back.)
So far I have tried looping to receive the server's input but without success. The server writes twice to the socket, so the client must read twice before trying to send its own message. If I read a third time the read blocks (which I think is the normal behaviour).
I tried using poll on the socket from the client's side to watch for POLLOUT events, but it does not seem to work.
int connect(){
unsigned int backlog = 10;
/*
struct sockaddr_in {
short sin_family; // e.g. AF_INET
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, below
char sin_zero[8]; // zero this if you want to
};
struct in_addr {
unsigned long s_addr; // load with inet_aton()
};
*/
struct sockaddr_in server{};
//Create socket
listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
if (listeningSocket == -1) {
spdlog::critical("Could not create socket");
}
spdlog::debug("Socket created.");
//Prepare the socket for incoming connections
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PortNumber); // NOLINT(hicpp-signed-bitwise)
if (bind(listeningSocket, (const struct sockaddr *) &server, sizeof(sockaddr_in)) < 0) {
spdlog::critical("bind failed. Error");
exit(-1);
}
spdlog::debug("Bind succeeded\n");
if (!listen(listeningSocket, static_cast<int>(backlog))) {
return listeningSocket;
}
return -1;
}
Handle the message
void* sendMessage(){
//Get the socket descriptor
int sock = socket;
int read_size;
const char *message;
char client_message[200];
//Send some messages to the client
message = "Greetings! I am your connection handler\n";
write(sock, message, strlen(message));
message = "Now type something and i shall apply the caesar cipher to it \n";
write(sock, message, strlen(message));
//Receive a message from client
while ((read_size = recv(sock, client_message, 200, 0)) > 0) {
//end of string marker
client_message[read_size] = '\0';
std::string temp(client_message);
temp = cipher->operate(temp);
//Send the message back to client
write(sock, temp.c_str(), strlen(temp.c_str()));
//clear the message buffer
memset(client_message, 0, 200);
}
if (read_size == 0) {
spdlog::debug("Client disconnected");
fflush(stdout);
} else if (read_size == -1) {
spdlog::error("recv failed: {}",errno);
}
return nullptr;
}
As for the client side:
//Connect to the server
void connect()
{
struct hostent *he;
struct sockaddr_in their_addr{}; /* connector's address information */
if ((he=gethostbyname(mHost.c_str())) == nullptr) { /* get the host info */
spdlog::error("gethostbyname");
}
if ((mSocket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
spdlog::error("socket");
exit(1);
}
their_addr.sin_family = AF_INET; /* host byte order */
their_addr.sin_port = htons(mPort); /* short, network byte order */ //NOLINT
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
bzero(&(their_addr.sin_zero), 8); /* zero the rest of the struct */
if (connect(mSocket, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1) {
spdlog::error("connect");
exit(1);
}
}
}
And try to send the message:
void sendMessage(){
#define MAX 100
if (!sockfd) {
sockfd = mSocket;
spdlog::info("Setting socket to {}", sockfd);
}
char buff[MAX];
struct pollfd fds[1];
fds[0].fd=sockfd;
while (( recv(sockfd, buff, 200, 0)) > 0) {
printf("From Server : %s", buff);
bzero(buff, sizeof(buff));
}
strcpy(buff, "PAPARI");
write(sockfd, buff, sizeof(buff));
bzero(buff, sizeof(buff));
read(sockfd, buff, sizeof(buff));
printf("From Server : %s", buff);
close(sockfd);
}
This will block after the two messages from the server are received by the client.
I have written a program for simple text chatting between server and client using socket programming. The server side runs okay since it's listening but when I run the client side program it runs but shows no output, meaning nothing shows up on server side if I type in Client side. Why am I not getting any response from Client side?
/****************** CLIENT CODE ****************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int clientSocket,n;
char buffer[256];
struct sockaddr_in serverAddr;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
clientSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Connect the socket to the server using the address struct ----*/
addr_size = sizeof serverAddr;
connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);
if (connect(clientSocket,(struct sockaddr *) &serverAddr,sizeof(serverAddr)) < 0)
error("ERROR connecting");
printf("Please enter the message: ");
bzero(buffer,256);
fgets(buffer,255,stdin);
n = write(clientSocket,buffer,strlen(buffer));
if (n < 0)
error("ERROR writing to socket");
bzero(buffer,256);
n = read(clientSocket,buffer,255);
if (n < 0)
error("ERROR reading from socket");
printf("%s\n",buffer);
close(clientSocket);
/*---- Read the message from the server into the buffer ----*/
//recv(clientSocket, buffer, 1024, 0);
/*---- Print the received message ----*/
//printf("Data received: %s",buffer);
return 0;
}
/****************** SERVER CODE ****************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
int main(){
int welcomeSocket, newSocket;
char buffer[256];
int n;
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error\n");
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
/*---- Send message to the socket of the incoming connection ----*/
bzero(buffer,256);
n = read(welcomeSocket,buffer,255);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(welcomeSocket,"I got your message",18);
if (n < 0) error("ERROR reading from socket");
printf("Here is the message: %s\n",buffer);
n = write(welcomeSocket,"I got your message",18);
if (n < 0) error("ERROR writing to socket");
close(newSocket);
close(welcomeSocket);
return 0;
}
In your server code the read() should use the socket descriptor returned from the accept() not from the call to socket(). So try reading using newSocket rather than welcomeSocket.
n = read(newSocket,buffer,255);
I'm using below code to create a server program in c. The code is taken from here
#include <Winsock.h>
#include <string.h>
#include <ws2tcpip.h>
#include<conio.h>
int main(){
int welcomeSocket, newSocket;
char buffer[1024];
struct sockaddr_in serverAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size;
/*---- Create the socket. The three arguments are: ----*/
/* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
welcomeSocket = socket(PF_INET, SOCK_STREAM, 0);
/*---- Configure settings of the server address struct ----*/
/* Address family = Internet */
serverAddr.sin_family = AF_INET;
/* Set port number, using htons function to use proper byte order */
serverAddr.sin_port = htons(7891);
/* Set IP address to localhost */
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
/* Set all bits of the padding field to 0 */
memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);
/*---- Bind the address struct to the socket ----*/
bind(welcomeSocket, (struct sockaddr *) &serverAddr, sizeof(serverAddr));
/*---- Listen on the socket, with 5 max connection requests queued ----*/
if(listen(welcomeSocket,5)==0)
printf("Listening\n");
else
printf("Error %d\n",listen(welcomeSocket,5));
/*---- Accept call creates a new socket for the incoming connection ----*/
addr_size = sizeof serverStorage;
newSocket = accept(welcomeSocket, (struct sockaddr *) &serverStorage, &addr_size);
/*---- Send message to the socket of the incoming connection ----*/
strcpy(buffer,"Hello World\n");
send(newSocket,buffer,13,0);
getch();
return 0;
}
I've changed the code little bit to make it work in dev-c but in the output it's printing error i.e it's executing the else condition. Anyone have any idea why? And how to debug this?
I've tried changing the port no. It didn't work.
On Windows, you have to initialize the networking subsystem first by calling WSAStartup, before you can make any calls to socket/network-related functions.
WSADATA wsaData;
int wsaRc = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (wsaRc != 0) {
fprintf(stderr, "WSAStartup failed with error: %d\n", wsaRc);
return 1;
}
/* Socket related functions callable from here on */
The example-code you've linked was written for UNIX systems, which do not have that API-requirement.
Please note, that you also
[...] must call the WSACleanup function for every successful
time the WSAStartup function is called.
(From the WSAStartup documentation).
I'm making a client program in C that has to deal with this situation:
1- server program receives udp datagram in port no 8080 sent by client with a port number X
2- server creates a new socket (TCP) in port number X
3- using this TCP socket, server reads a string sent by the client
(running on localhost)
I don't need to make the server program, it's already done. The points 1 and 2 are covered, but I've been a couple of days trying to work out the 3rd point and I'm not able to make it work ><
The code I've got for the client is this:
#define MYPORT 8080
int main(int argc, char *argv[ ]) {
int sockfd;
/* connector’s address information */
struct sockaddr_in their_addr;
struct hostent *he;
int numbytes;
int sockfd2, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc != 3) {
fprintf(stderr, "Usage: %s <hostname> <message>\n", argv[0]);
exit(1);
}
/* get the host info */
if ((he = gethostbyname(argv[1])) == NULL) {
perror("Error obtaining the client. \n");
exit(1);
}
else printf("Client obtained\n");
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Error creating UDP socket\n");
exit(1);
}
else printf("UDP Socket done\n");
their_addr.sin_family = AF_INET;
printf("Port: 8080\n");
their_addr.sin_port = htons(MYPORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8);
sockfd2 = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd2 < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
//sending port where the TCP socket will be associated
//server client connects correctly to this port
//and the code it's working fine in this point
if((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1)
{
perror("Client-sendto() error lol!");
exit(1);
}
//port is sent, now let's connect to the port by tcp and write the string
//not working properly from now on
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(atoi(argv[2]));
if (bind(sockfd2,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR connecting");
listen(sockfd2, 5);
accept(sockfd2, 0, 0);
printf("accepted!\n");
//sending the string to the TCP Port...
if((numbytes = sendto(sockfd2, "hi", 2, 0, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr))) == -1)
{
printf("Client-sendto()-TCP error\n");
exit(1);
}
if (close(sockfd) != 0) printf("Client-sockfd-UDP closing is failed!\n");
else printf("Client-sockfd-UDP successfully closed!\n");
if (close(sockfd) != 0) printf("Client-sockfd2-TCP closing is failed!\n");
else printf("Client-sockfd2-TCP successfully closed!\n");
return 0;
}
The code works for the first two steps, but in the last step, it seems it's not connecting well with the TCP port, because my client program ends but my server program says that he receives null.
And of course I'm always sending ports > 1024
Thanks in advance, any help will be so appreciated.
listen(sockfd2, 5);
accept(sockfd2, 0, 0);
printf("accepted!\n");
I haven't read all your code, but the above (at least) is wrong. You absolutely need to retain the return value of accept: it's the socket you need to write to!
accept returns a file descriptor for the new TCP socket that has just been created for communicating with the "server" in your case. You need to use that as the file descriptor you write your string to.
(The sendto call just after that, apart from using the wrong socket, is a bit suspicious since the server will have no way to determine how much data to read/where the message stops. Passing a length of 3 (to include the \0 byte, would be a bit less suspicious.)
Based from the answers I got from this thread, I've created this:
//Server
sock_init(); //from SFL, see http://legacy.imatix.com/html/sfl/
timeout = 50000;
serv_sock_input[0] = TCP(1234);
serv_sock_input[1] = UDP(9876);
input_protocols[0] = "tcp";
input_protocols[1] = "udp";
while (1)
{
FD_ZERO(&sock_set);
for (x = 0; x<number_of_inputs; x++)
{
FD_SET(serv_sock_input[x], &sock_set);
}
select_timeout.tv_sec = timeout;
select_timeout.tv_usec = 0;
if (select(0, &sock_set, NULL, NULL, &select_timeout) == 0)
printf("No requests");
else
{
for (x = 0; x<number_of_inputs; x++)
{
if (FD_ISSET(serv_sock_input[x],&sock_set))
{
printf("\nRequest on port %d: \n", x);
if ((strcmp(input_protocols[x],"tcp")) == 0) //in this case, 0 returned == TRUE
{
accept_socket(serv_sock_input[x]);
printf("Input TCP Port %d\n",x);
close_socket(serv_sock_input[x]);
}
else
{
printf("Input UDP Port %d\n",x);
}
}
}
}
}
sock_term();
}
int TCP (unsigned short port)
{
int sock;
struct sockaddr_in servAddr;
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
exit(1);
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port);
if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
exit(1);
if (listen(sock, 5) < 0)
exit(1);
return sock;
}
int UDP (unsigned short port)
{
int sock; /* socket to create */
struct sockaddr_in servAddr; /* Local address */
/* Create socket for sending/receiving datagrams */
if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
exit(1);
/* Construct local address structure */
memset(&servAddr, 0, sizeof(servAddr)); /* Zero out structure */
servAddr.sin_family = AF_INET; /* Internet address family */
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
servAddr.sin_port = htons(port); /* Local port */
/* Bind to the local address */
if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0)
exit(1);
return sock;
}
//Client
sock_init();
if ((client_sock_output = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
exit(1);
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
client_addr.sin_port = htons(1234);
if (connect(client_sock_output, (struct sockaddr *) &client_addr, sizeof(client_addr)) < 0)
exit(1);
closesocket(client_sock_output);
sock_term();
When the server starts, the server gets blocked at the if(select(...)) statement.
So when I run the Server, and then the client, the client connects to the server (sometimes it takes a couple times to run the client before they connect). Then the if(select...)) statement is no longer true and it proceeds to the else.
After that, the client closes the connection, and the program. However, and this is where my problem happens, the if(select(...)) statement is always false. I get this output:
Request on port 0:
Input TCP Port 0
Request on port 1:
Input UDP Port 1
This output repeats forever. How come it doesn't get stuck at the if(select(...))?
You have two problems: you don't understand how accept() works in TCP, and you need to read the incoming data in UDP.
select() tells you that a listening socket has connection to accept, or reading socket has data to read.
For select to stop telling you this, you need to actually read the data or accept the connection.
In your UDP branch, you need to call receiv to actually get the data. If you don't, select will keep telling you that you have data.
In your TCP branch, you call accept_socket. I don't know what is your implementation of it, but it's most probably wrong to close the socket you just called accept() on. accept() returns a new socket for you - the one you should be using for IO. If anything needs to be closed, it's that new socket.
Please check why you have this in server.
if (select(0, &sock_set, NULL, NULL, &select_timeout) == 0)
replace it with
if (select(maxDescPlus1, &sock_set, NULL, NULL, &select_timeout) == 0)
where maxDescPlus1 --> is number of descriptors to select plus 1 value.