#include <pthread.h>
#include <iostream>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <semaphore.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iterator>
const int NET_BUFFER_NUMBER=1024;
const int THREAD_BUFFER_NUMBER=10;
const int WORK_THREAD_NUMBER=20;
//this struct for thread deal socket need data
struct data_buffer
{
char data_array[NET_BUFFER_NUMBER];
int data_len;
struct sockaddr_in src_socket;
const data_buffer& operator=(const data_buffer& rhs)
{
data_len = rhs.data_len;
for (int i=0; i<data_len; i++)
{
data_array[i] = rhs.data_array[i];
}
src_socket = rhs.src_socket;
return rhs;
}
};
//main thread and dispatch thread
struct data_buffer globe_buffer[THREAD_BUFFER_NUMBER];
pthread_mutex_t main_mutex;
pthread_cond_t main_cond;
bool can_read;
//use threads pool manage
//pthread_mutex_t mutex[WORK_THREAD_NUMBER];
pthread_mutex_t mutex;
pthread_cond_t cond;
bool is_start[WORK_THREAD_NUMBER];
struct thread_arg
{
const struct data_buffer* ptr_data;
int self_index;//is_start array index,also mutex array
};
void* thread_function(void* args)
{
//because of after args will changes value
struct thread_arg* ptr_arg = (struct thread_arg*)args;
int index = ptr_arg->self_index;
const struct data_buffer* ptr_src_data = ptr_arg->ptr_data;
//std::cout<<"create thread index is:"<<index<<"/t data address is:"<<ptr_src_data<<std::endl;
int my_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (my_socket == -1)
{
perror("create my socket failure in thread function");
pthread_exit(NULL);
}
struct data_buffer deal_data[THREAD_BUFFER_NUMBER];
while (true)
{
pthread_mutex_lock(&mutex);
while (!is_start[index])
{
pthread_cond_wait(&cond, &mutex);
}
for (int j=0; j<THREAD_BUFFER_NUMBER; j++)
{
deal_data[j] = ptr_src_data[j];//copy self will deal data
}
pthread_mutex_unlock(&mutex);
//copy the same data to client
for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
{
sleep(5);
sendto(my_socket, deal_data[i].data_array, deal_data[i].data_len, 0, (sockaddr*)&(deal_data[i].src_socket), sizeof(deal_data[i].src_socket));
}
is_start[index] = false;//notice self is idle
}//end of while
close(my_socket);
return NULL;
}
bool create_threads(int create_count, struct data_buffer data_args[])
{
pthread_attr_t attr;
std::size_t stack_size;
struct thread_arg args;
args.ptr_data = data_args;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN*3);
for (int i=0; i<WORK_THREAD_NUMBER; i++)
{
pthread_t ptd;
args.self_index = i;
if (pthread_create(&ptd, &attr, &thread_function, (void*)&args) != 0)
{
perror("create failure");
return false;
}
}
return true;
}
void* dispatch(void* args)
{
struct data_buffer temp[THREAD_BUFFER_NUMBER];
if (pthread_mutex_init(&mutex, NULL) != 0)
{
perror("init lock failure in dispatch function");
pthread_exit(NULL);
}
if (pthread_cond_init(&cond, NULL) != 0)
{
perror("inin cond failure");
pthread_exit(NULL);
}
for (int i=0; i<WORK_THREAD_NUMBER; i++)
{
is_start[i] = false;//block all work thread
}
if (!create_threads(WORK_THREAD_NUMBER, temp))
{
perror("create threads failure");
pthread_exit(NULL);
}
while (true)
{
pthread_mutex_lock(&main_mutex);
while (!can_read)
{
pthread_cond_wait(&main_cond, &main_mutex);
}
std::cout<<"sem wait wake up"<<std::endl;
//forbidden main loop thread write data,or maybe read dirty data
//pthread_mutex_lock(&main_mutex);
//if last work thread can not complete copy data, we can not write to temp
for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
{
temp[i] = globe_buffer[i];
}
//dispatch work start, if not idle thread, it will be block.
while (true)
{
int j;
for (j=0; j<WORK_THREAD_NUMBER; j++)
{
//find one idle thread, no need lock
if (!is_start[j])
{
//signal this thread start work
pthread_mutex_lock(&mutex);
is_start[j] = true;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
break;//only break for
}
}
if (j<WORK_THREAD_NUMBER)//find one idle thread and start it
{
std::cout<<"find an idle thread:"<<j<<std::endl;
break;//break dispatch while
}
}//end of find idle
//std::cout<<"dispatch successful"<<std::endl
can_read = false;
pthread_mutex_unlock(&main_mutex);
}//end of dispatch
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
}
int main(int argc, char* argv[])
{
int listen_socket = socket(PF_INET, SOCK_DGRAM, 0);
if (listen_socket == -1)
{
perror("create listen socket failure");
return -1;
}
//sizeof(sockaddr_in) = sizeof(sockaddr)
//sockaddr purose = sockaddr_in purose
struct sockaddr_in addr;
bzero(&addr, sizeof(sockaddr_in));
addr.sin_family = PF_INET;
addr.sin_port = htons(1120);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(listen_socket, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1)
{
perror("bind listen_socket failure");
close(listen_socket);
return -1;
}
if (pthread_mutex_init(&main_mutex, NULL) != 0)
{
perror("main_mutex init failure");
close(listen_socket);
return -1;
}
if (pthread_cond_init(&main_cond, NULL) != 0)
{
perror("main_cond init failure");
close(listen_socket);
return -1;
}
//create distpach thread
can_read = false;
pthread_t pt;
if (pthread_create(&pt, NULL, &dispatch, NULL) != 0)
{
perror("create dispatch thread failure");
close(listen_socket);
return -1;
}
//main receive loop
char buffer[NET_BUFFER_NUMBER];
bzero(buffer, sizeof(buffer));
struct sockaddr_in client;
int actual_len=0;
socklen_t sock_len = sizeof(sockaddr_in);
struct data_buffer temp[THREAD_BUFFER_NUMBER];
int index=0;
while (true)
{
if ((actual_len=recvfrom(listen_socket, buffer, NET_BUFFER_NUMBER, 0, (sockaddr*)&client, &sock_len)) == -1)
{
//allow error
continue;
}
else
{
if (index >= THREAD_BUFFER_NUMBER)
{
pthread_mutex_lock(&main_mutex);
for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
{
globe_buffer[i] = temp[i];
}
index = 0;
can_read = true;
pthread_cond_broadcast(&main_cond);
pthread_mutex_unlock(&main_mutex);
}
else
{
temp[index].data_len = actual_len;
for (int k=0; k<actual_len; k++)
{
temp[index].data_array[k] = buffer[k];
}
temp[index++].src_socket = client;
}
}
}
pthread_mutex_destroy(&main_mutex);
pthread_cond_destroy(&main_cond);
return 0;
}
#include <iostream>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <semaphore.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iterator>
const int NET_BUFFER_NUMBER=1024;
const int THREAD_BUFFER_NUMBER=10;
const int WORK_THREAD_NUMBER=20;
//this struct for thread deal socket need data
struct data_buffer
{
char data_array[NET_BUFFER_NUMBER];
int data_len;
struct sockaddr_in src_socket;
const data_buffer& operator=(const data_buffer& rhs)
{
data_len = rhs.data_len;
for (int i=0; i<data_len; i++)
{
data_array[i] = rhs.data_array[i];
}
src_socket = rhs.src_socket;
return rhs;
}
};
//main thread and dispatch thread
struct data_buffer globe_buffer[THREAD_BUFFER_NUMBER];
pthread_mutex_t main_mutex;
pthread_cond_t main_cond;
bool can_read;
//use threads pool manage
//pthread_mutex_t mutex[WORK_THREAD_NUMBER];
pthread_mutex_t mutex;
pthread_cond_t cond;
bool is_start[WORK_THREAD_NUMBER];
struct thread_arg
{
const struct data_buffer* ptr_data;
int self_index;//is_start array index,also mutex array
};
void* thread_function(void* args)
{
//because of after args will changes value
struct thread_arg* ptr_arg = (struct thread_arg*)args;
int index = ptr_arg->self_index;
const struct data_buffer* ptr_src_data = ptr_arg->ptr_data;
//std::cout<<"create thread index is:"<<index<<"/t data address is:"<<ptr_src_data<<std::endl;
int my_socket = socket(AF_INET, SOCK_DGRAM, 0);
if (my_socket == -1)
{
perror("create my socket failure in thread function");
pthread_exit(NULL);
}
struct data_buffer deal_data[THREAD_BUFFER_NUMBER];
while (true)
{
pthread_mutex_lock(&mutex);
while (!is_start[index])
{
pthread_cond_wait(&cond, &mutex);
}
for (int j=0; j<THREAD_BUFFER_NUMBER; j++)
{
deal_data[j] = ptr_src_data[j];//copy self will deal data
}
pthread_mutex_unlock(&mutex);
//copy the same data to client
for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
{
sleep(5);
sendto(my_socket, deal_data[i].data_array, deal_data[i].data_len, 0, (sockaddr*)&(deal_data[i].src_socket), sizeof(deal_data[i].src_socket));
}
is_start[index] = false;//notice self is idle
}//end of while
close(my_socket);
return NULL;
}
bool create_threads(int create_count, struct data_buffer data_args[])
{
pthread_attr_t attr;
std::size_t stack_size;
struct thread_arg args;
args.ptr_data = data_args;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN*3);
for (int i=0; i<WORK_THREAD_NUMBER; i++)
{
pthread_t ptd;
args.self_index = i;
if (pthread_create(&ptd, &attr, &thread_function, (void*)&args) != 0)
{
perror("create failure");
return false;
}
}
return true;
}
void* dispatch(void* args)
{
struct data_buffer temp[THREAD_BUFFER_NUMBER];
if (pthread_mutex_init(&mutex, NULL) != 0)
{
perror("init lock failure in dispatch function");
pthread_exit(NULL);
}
if (pthread_cond_init(&cond, NULL) != 0)
{
perror("inin cond failure");
pthread_exit(NULL);
}
for (int i=0; i<WORK_THREAD_NUMBER; i++)
{
is_start[i] = false;//block all work thread
}
if (!create_threads(WORK_THREAD_NUMBER, temp))
{
perror("create threads failure");
pthread_exit(NULL);
}
while (true)
{
pthread_mutex_lock(&main_mutex);
while (!can_read)
{
pthread_cond_wait(&main_cond, &main_mutex);
}
std::cout<<"sem wait wake up"<<std::endl;
//forbidden main loop thread write data,or maybe read dirty data
//pthread_mutex_lock(&main_mutex);
//if last work thread can not complete copy data, we can not write to temp
for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
{
temp[i] = globe_buffer[i];
}
//dispatch work start, if not idle thread, it will be block.
while (true)
{
int j;
for (j=0; j<WORK_THREAD_NUMBER; j++)
{
//find one idle thread, no need lock
if (!is_start[j])
{
//signal this thread start work
pthread_mutex_lock(&mutex);
is_start[j] = true;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
break;//only break for
}
}
if (j<WORK_THREAD_NUMBER)//find one idle thread and start it
{
std::cout<<"find an idle thread:"<<j<<std::endl;
break;//break dispatch while
}
}//end of find idle
//std::cout<<"dispatch successful"<<std::endl
can_read = false;
pthread_mutex_unlock(&main_mutex);
}//end of dispatch
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
}
int main(int argc, char* argv[])
{
int listen_socket = socket(PF_INET, SOCK_DGRAM, 0);
if (listen_socket == -1)
{
perror("create listen socket failure");
return -1;
}
//sizeof(sockaddr_in) = sizeof(sockaddr)
//sockaddr purose = sockaddr_in purose
struct sockaddr_in addr;
bzero(&addr, sizeof(sockaddr_in));
addr.sin_family = PF_INET;
addr.sin_port = htons(1120);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if (bind(listen_socket, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1)
{
perror("bind listen_socket failure");
close(listen_socket);
return -1;
}
if (pthread_mutex_init(&main_mutex, NULL) != 0)
{
perror("main_mutex init failure");
close(listen_socket);
return -1;
}
if (pthread_cond_init(&main_cond, NULL) != 0)
{
perror("main_cond init failure");
close(listen_socket);
return -1;
}
//create distpach thread
can_read = false;
pthread_t pt;
if (pthread_create(&pt, NULL, &dispatch, NULL) != 0)
{
perror("create dispatch thread failure");
close(listen_socket);
return -1;
}
//main receive loop
char buffer[NET_BUFFER_NUMBER];
bzero(buffer, sizeof(buffer));
struct sockaddr_in client;
int actual_len=0;
socklen_t sock_len = sizeof(sockaddr_in);
struct data_buffer temp[THREAD_BUFFER_NUMBER];
int index=0;
while (true)
{
if ((actual_len=recvfrom(listen_socket, buffer, NET_BUFFER_NUMBER, 0, (sockaddr*)&client, &sock_len)) == -1)
{
//allow error
continue;
}
else
{
if (index >= THREAD_BUFFER_NUMBER)
{
pthread_mutex_lock(&main_mutex);
for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
{
globe_buffer[i] = temp[i];
}
index = 0;
can_read = true;
pthread_cond_broadcast(&main_cond);
pthread_mutex_unlock(&main_mutex);
}
else
{
temp[index].data_len = actual_len;
for (int k=0; k<actual_len; k++)
{
temp[index].data_array[k] = buffer[k];
}
temp[index++].src_socket = client;
}
}
}
pthread_mutex_destroy(&main_mutex);
pthread_cond_destroy(&main_cond);
return 0;
}