Reputation: 1561
I have written a C program that I hope to use as a simple TCP/IP based service. The program has to open a listening TCP socket. Whenever someone writes to the socket, my program has to read the message, do a little processing, then send a different message back. The program has to run forever.
The program compiles and runs. (I’m using gcc 7.4.0) Trouble is, after a couple thousand messages are successfully processed without any problems, the program starts printing this:
...
Connection FAILED :: Value of errno: 24
Connection FAILED :: Value of errno: 24
Connection FAILED :: Value of errno: 24
Connection FAILED :: Value of errno: 24
...
Errno 24 means “too many file descriptors open,” which makes me wonder if my program is allocating something (sockets? memory?) and not properly deallocating it later. But I can’t spot where I’m going wrong.
Let me show you my code. I followed a tutorial I liked, where they gathered all the relevant socket info in one struct:
typedef struct{
int sock;
struct sockaddr address;
socklen_t addr_len;
} connection_t;
The main()
sets up the socket, then listens to it in an infinite loop to listen:
int main(int argc, char ** argv) {
int sock = -1;
struct sockaddr_in address;
int port = 12345;
connection_t* connection;
// Create the listening socket
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock <= 0){
fprintf(stderr, "%s: error: cannot create socket\n", argv[0]);
return -3;
}
// Bind socket to port
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
if (bind(sock, (struct sockaddr *)&address, sizeof(struct sockaddr_in)) < 0){
fprintf(stderr, "%s: error: cannot bind socket to port %d\n", argv[0], port);
return -4;
}
// Listen on the port
if (listen(sock, 5) < 0){
fprintf(stderr, "%s: error: cannot listen on port\n", argv[0]);
return -5;
}
// We're ready to go...!
printf("%s: ready and listening\n", argv[0]);
while (1){
// Accept incoming connections
connection = (connection_t *)malloc(sizeof(connection_t));
connection->addr_len = 20;
connection->sock = accept(sock, &connection->address, &connection->addr_len);
if (connection->sock <= 0){
// ***********************************************
// *** This is where the error happens!
printf("Connection FAILED :: Value of errno: %d\n ", errno);
// ***********************************************
}
else{
printf("SERVER... New Msg received...\n");
readMsgAndReply( connection );
}
free(connection);
}
return 0;
}
You’ll note that I get my “Connection FAILED” message when accept()
cannot successfully accept a new, incoming connection – I wish I knew why.
If accept()
is successful, my code calls readMsgAndReply():
void readMsgAndReply( connection* conn ){
char* buffer;
char* reply = "Your Msg was received!";
int ret, len, replyLen;
long addr = 0;
// First call to read() measures the length of the sent message
ret = read(conn->sock, &len, sizeof(int));
if( ret < 0 ){
printf( "***readMsgAndReply() ERROR: read() error\n" );
}
if( len > 0 ){
addr = (long)((struct sockaddr_in *)&conn->address)->sin_addr.s_addr;
buffer = (char *)malloc((len+1)*sizeof(char));
buffer[len] = 0;
// Second call to read() actually reads the message from the socket
ret = read(conn->sock, buffer, len);
if( ret < 0 ){
printf( "***readMsgAndReply() ERROR: ret < 0\n");
}
else{
printf("***readMsgAndReply() message size :: %d\n", len);
printf("***readMsgAndReply() is :: \"%s\"\n", buffer);
}
// write reply message back to the client
replyLen = write(conn->sock, reply, strlen(reply));
if(replyLen > 0)
printf("===> Reply written, %d bytes sent!\n", replyLen);
else
printf("---> No reply written\n");
free(buffer);
}
}
There you have it. This code works beautifully for the first several thousand received messages, then spits out ERRNO 24. Anyone see what I’m doing wrong?
Upvotes: 0
Views: 469
Reputation: 456
Before exiting function readMsgAndReply you need to close socket.
close(connection->sock);
Upvotes: 2