Solved

Socket Programming (Unix)

Posted on 2016-07-27
8
99 Views
Last Modified: 2016-07-31
Dear Experts,

I have a code socket server, listen on TCP port 8888.
I use top command, it will see that actually used memory grows each time a new connection is accepted while it is not released after the thread finishes its work.

Test.c

#include<stdio.h>
#include<string.h>    //strlen
#include<stdlib.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write

#include<pthread.h> //for threading , link with lpthread

void *connection_handler(void *);

int main(int argc, char *argv[]) {
	int socket_desc, new_socket, c, *new_sock;
	struct sockaddr_in server, client;

	//Create socket
	socket_desc = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_desc == -1) {
		printf("Could not create socket");
	}

	//Prepare the sockaddr_in structure
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(8888);

	//Bind
	if (bind(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) {
		puts("bind failed");
		return 1;
	}
	puts("bind done");

	//Listen
	listen(socket_desc, 3);

	//Accept and incoming connection
	puts("Waiting for incoming connections...");
	c = sizeof(struct sockaddr_in);
	while ((new_socket = accept(socket_desc, (struct sockaddr *) &client,
			(socklen_t*) &c))) {
		puts("Connection accepted");

		pthread_t sniffer_thread;
		new_sock = (int*) malloc(sizeof(int));
		*new_sock = new_socket;

		if (pthread_create(&sniffer_thread, NULL, connection_handler,
				(void*) new_sock) < 0) {
			perror("could not create thread");
			return 1;
		}

		//Now join the thread , so that we dont terminate before the thread
		//pthread_join( sniffer_thread , NULL);
		puts("Handler assigned");
	}

	if (new_socket < 0) {
		perror("accept failed");
		return 1;
	}

	return 0;
}

/*
 * This will handle connection for each client
 * */
void *connection_handler(void *socket_desc) {
	//Get the socket descriptor
	int sock = *(int*) socket_desc;
	int read_size;
	char client_message[2000];

	struct timeval tv;
	tv.tv_sec = 3; /* Timeout in seconds */
	setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (struct timeval *) &tv,
			sizeof(struct timeval));
	setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *) &tv,
			sizeof(struct timeval));

	read_size = recv(sock, client_message, 100, 0);
	client_message[read_size] = '\0';

	printf("CLIENT SEND>%s<\n", client_message);

	write(sock , client_message , strlen(client_message));

	//Free the socket pointer
	free(socket_desc);
	close(sock);
	pthread_exit(NULL);

Open in new window

Build:
gcc -lpthread Test.c -o Test

Help me, please.
Thanks.
0
Comment
Question by:ldvhai
  • 5
  • 2
8 Comments
 
LVL 35

Expert Comment

by:mccarl
ID: 41732253
I use top command, it will see that actually used memory grows each time a new connection is accepted while it is not released after the thread finishes its work

The main thing I would say is to be careful assuming that you have a memory leak just by looking at top. It could very well be that the memory IS being released, it is just that next memory allocation isn't necessarily using previously released memory. Perhaps, it is only when memory resource are close to exhausted that it goes back and starts using previously freed memory.

The other point that I would make is that you should be able to get rid of the malloc/free calls in the above code, because the sizeof(void*) should be big enough to hold your int, so you could do this...

#include<stdio.h>
#include<string.h>    //strlen
#include<stdlib.h>    //strlen
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr
#include<unistd.h>    //write

#include<pthread.h> //for threading , link with lpthread

void *connection_handler(void *);

int main(int argc, char *argv[]) {
	int socket_desc, new_socket, c, *new_sock;
	struct sockaddr_in server, client;

	//Create socket
	socket_desc = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_desc == -1) {
		printf("Could not create socket");
	}

	//Prepare the sockaddr_in structure
	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(8888);

	//Bind
	if (bind(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) {
		puts("bind failed");
		return 1;
	}
	puts("bind done");

	//Listen
	listen(socket_desc, 3);

	//Accept and incoming connection
	puts("Waiting for incoming connections...");
	c = sizeof(struct sockaddr_in);
	while ((new_socket = accept(socket_desc, (struct sockaddr *) &client,
			(socklen_t*) &c))) {
		puts("Connection accepted");

		pthread_t sniffer_thread;

		if (pthread_create(&sniffer_thread, NULL, connection_handler,
				(void*) new_socket) < 0) {
			perror("could not create thread");
			return 1;
		}

		//Now join the thread , so that we dont terminate before the thread
		//pthread_join( sniffer_thread , NULL);
		puts("Handler assigned");
	}

	if (new_socket < 0) {
		perror("accept failed");
		return 1;
	}

	return 0;
}

/*
 * This will handle connection for each client
 * */
void *connection_handler(void *socket_desc) {
	//Get the socket descriptor
	int sock = (int) socket_desc;
	int read_size;
	char client_message[2000];

	struct timeval tv;
	tv.tv_sec = 3; /* Timeout in seconds */
	setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (struct timeval *) &tv,
			sizeof(struct timeval));
	setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *) &tv,
			sizeof(struct timeval));

	read_size = recv(sock, client_message, 100, 0);
	client_message[read_size] = '\0';

	printf("CLIENT SEND>%s<\n", client_message);

	write(sock , client_message , strlen(client_message));

	close(sock);
	pthread_exit(NULL);

Open in new window

1
 
LVL 2

Author Comment

by:ldvhai
ID: 41732319
Hi mccarl,

Thanks for your answer.

I run your code, but memory grows each time a new connection is accepted while it is not released after the thread finishes its work.

1)      Do not run Test
 1.png2)      Run Test, Do not send request to Port 8888
 2.png
3)      Send 1000 request to Port 8888
Command:
# for i in {1..1000};do echo -n ${i} "---> ";echo -n "TEST_RAM" | nc localhost 8888;echo "";sleep 0.005;done
•      RAM info which 1000 connection.
 3.png
 4.png•      RAM info when connection release, only server listen port 8888
 5.png 6.png4)      Exit Test
 7.png
0
 
LVL 35

Expert Comment

by:mccarl
ID: 41732362
As I said previously, you can't look at those numbers and assume that the memory is NOT being released.
0
 
LVL 2

Author Comment

by:ldvhai
ID: 41732560
Hi mccarl,

Thanks for your answer.
I send unlimited requests to the server
After a period of time , used memory grows and Test program dead.
Thus, this program does not release memory.

Is it right?

Help me, please.
Thanks.
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 32

Accepted Solution

by:
sarabande earned 500 total points
ID: 41732964
to add to previous comments:

you may try to comment pthread_exit call. the thread would terminate at return  anyhow. pthread_exit wouldn't release resources of the main thread regarding this thread. this is not small if you have build in debug mode. you also could/should try to call pthread_attr_destroy within the thread since even the 'attr' argument was NULL at pthread_create. a default attribute resource was created nevertheless.

also note that the tcp/ip subsystem is running asynchronously. hence after the recv the tcp still holds buffers and resources especially if the client would not close and shutdown immediately after send.

actually each of your threads should not end before the connection to their clients was not orderly run to shutdown. i would say you need at least to wait 10 seconds before you could terminate the thread with return to make sure that the resources used for the connection could be freed since both sides were down.

in any case if you have a debug build all memory measurements are waste since the debugger will not spare memory allocated but adds some debug space to each allocation which later could prevent from memory to be reused since it was defragmented.

Sara
1
 
LVL 2

Author Comment

by:ldvhai
ID: 41736949
Hi sarabande,

Thanks for your answer.
You can edit code for me with pthread_attr_destroy, please.


Thanks.
0
 
LVL 2

Author Comment

by:ldvhai
ID: 41736996
Hi sarabande,

I fixed success.

Thank you very much.
0
 
LVL 2

Author Closing Comment

by:ldvhai
ID: 41736998
I fixed by pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

Thanks.
1

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now