-
threads and processes
I have problem with simple short code. It's example of usage of TCP communication. 6 Client processes initialized with fork() are sending simultaneously random numbers from 1 to 5 to server (in a infinite loop with random pause before sending another number) . Server responds with the same number. To receive and respond server uses threads in a loop.
Loop waits for connection and when some process wants to connect it creates one thread for it. So we have 6 client processes and 6 server threads.
The problem- All threads are used in the communication but not all server processes are used. When I use only 3 threads and processes instead of 6 all are in use. When I use 6 processes only 4 are in use. When I use 30 only ONE process is receiving and responding.
Maybe someone know how to make ALL processes to work in communication?
-
Do you want us to make random guesses based on your description of the problem?
Or are you going to post some code?
-
Excuse me. You're right:
global:
Code:
int num=5; //number of processes
int num2=1; //used to name threads
loop in which server waits for connections and starts threads
Code:
void server_loop(int socketfd) {
for(;;){
struct sockaddr_in client_addr;
int client_addr_len=sizeof(client_addr);
int con_sockfd = accept(socketfd, (struct sockaddr*)&client_addr, &client_addr_len);
if(con_sockfd != -1) {
printf("serwer: odebrano polaczenie od: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
pthread_t watek;
if(pthread_create(&watek, NULL, server_function, (void *)&con_sockfd) ) {
fprintf(stderr, "Blad pthread_create\n");
exit(-1);
}
} else {
perror("bladd accept w server_loop");
}
}
}
thread code:
Code:
void *server_function(void *socketfd_p) {
int nr=num2;
num2++;
int socketfd=*((int*)socketfd_p);
int param=1;
long long int result;
while(1){
if(recv(socketfd, ¶m, sizeof(param), 0) != sizeof(param)) {
perror("b≥±d recv w server_function");
}
result = param;
printf("serwer- odbr: %d wys: %ld\n", param, result);
if(send(socketfd, &result, sizeof(result), 0) != sizeof(result)) {
perror("b≥±d send w server_function");
}
printf("watek %d\n", nr);
}
pthread_exit(NULL);
}
client function - sending number receiving answer from server
Code:
int client_function(int socketfd, int pnum) {
int param, pauza;
long long int result;
for(;;){
pauza = rand() % 5;
printf("pauza %d\n", pauza);
sleep(pauza);
param= rand() % 5;
printf("param %d\n", param);
if(send(socketfd, ¶m, sizeof(param), 0) != sizeof(param)) {
perror("b≥±d send w client_funcion");
return -1;
}
if(recv(socketfd, &result, sizeof(result), 0) != sizeof(result)) {
perror("b≥±d recv w client_funcion");
return -1;
}
printf("klient %d- wys: %d odbr: %ld\n",pnum, param, result);
}
return 0;
}
main function
It is one code for server and client. It depends from start arguments which one you start.
Code:
int main(int argc, char** argv) {
int socketfd;
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_port=htons(SERV_SOCK_PORT);
if(argc < 2) {
printf("sposÛb uruchomienia: %s SERVER | CLIENT <adres>\n", argv[0]);
exit(1);
}
if(!strncmp(argv[1], "SERVER", 6)) {
struct hostent *host;
char hostname[100];
gethostname(hostname,100);
host=gethostbyname(hostname);
if (host == NULL) {
perror("b≥±d gethostbyname");
exit(1);
}
printf("startujÍ serwer pod adresem %s (IP=%s) na gnieºdzie %d\n", host->h_name, inet_ntoa(*((struct in_addr *)host->h_addr)), SERV_SOCK_PORT);
socketfd=socket(PF_INET, SOCK_STREAM, 0);
if(socketfd == -1) {
perror("blad socket w main (serwer)");
return -1;
}
// bind
addr.sin_addr.s_addr=INADDR_ANY;
if(bind(socketfd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
perror("b≥±d bind w main");
return -1;
}
// listen
if(listen(socketfd, 5) == -1) {
perror("b≥±d listen w main");
return -1;
}
server_loop(socketfd);
} else if(!strncmp(argv[1], "CLIENT", 6)) {
//starting another processes with fork()
int i;
for (i=0;i<num;i++){
srand(time(NULL) * i *13 );
if (fork()==0){
num=i;
i=6;
}
}
printf("startuj klienta %d\n",num);
socketfd=socket(PF_INET, SOCK_STREAM, 0);
if(socketfd == -1) {
perror("blad socket w main (klient)");
return -1;
}
// connect
addr.sin_addr.s_addr=inet_addr(argv[2]);
if(connect(socketfd, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
perror("blad connect w main");
return -1;
}
//starting client function (after fork())
client_function(socketfd,num);
close(socketfd);
return 0;
} else {
printf("start arguments: %s SERVER | CLIENT <adres>\n", argv[0]);
}
return 0;
}
-
> if(pthread_create(&watek, NULL, server_function, (void *)&con_sockfd)
This is essentially the same problem as returning a pointer to a local variable. The value it contains at the point the thread is created could well have changed (you're in a loop) before the thread actually gets to read it.
The more heavily loaded your server is, the more likely that you're opening another connection before the first thread has got going.
The safe way to pass data into a thread is through malloc.
Code:
int *p = malloc( sizeof(*p) ); // room for one int (or it could be any struct if you wanted)
*p = con_sockfd;
pthread_create(&watek, NULL, server_function, p);
The thread function then does
Code:
void *server_function(void *socketfd_p) {
int *p = socketfd_p; // cast back to original pointer type
int socket = *p;
free(p); // all done with the parameter memory
}
-