Unix下的I/O多路复用例子,用于服务器端的构造

来源:互联网 发布:相片打印软件推荐 编辑:程序博客网 时间:2024/05/22 18:33
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <signal.h>
#define SERVER_PORT 8764
#define BACKLOG 5
int status = -1;
struct SockFD
{
int sock_fd;
struct SockFD * next;
};
struct SockFD * table = 0;
pthread_mutex_t mutex;
void * server(void * args)
{
pthread_mutex_init(&mutex , 0);

int svr_fd = socket(PF_INET , SOCK_STREAM , 0);
if (svr_fd == -1)
{
  perror("server socket");
  
  pthread_exit(&status);
}

struct sockaddr_in svrAddr;
svrAddr.sin_family = PF_INET;
svrAddr.sin_port = htons(SERVER_PORT);
svrAddr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(svr_fd , (struct sockaddr *)&svrAddr , sizeof(svrAddr)) == -1)
{
  perror("bind");
  
  close(svr_fd);
  
  pthread_exit(&status);
}

if (listen(svr_fd , BACKLOG) == -1)
{
  perror("listen");
  
  close(svr_fd);
  
  pthread_exit(&status);
}

int fd = 0;
struct sockaddr_in addr;
unsigned int size = sizeof(addr);
while ((fd = accept(svr_fd , (struct sockaddr *)&addr , &size)) != -1)
{
   pthread_mutex_lock(&mutex);
   struct SockFD * node = (SockFD *)malloc(sizeof(SockFD));
   memset(node , 0x00 , sizeof(SockFD));
   node->sock_fd = fd;
  
   if (table == 0)
    table = node;
   else
   {
    node->next = table;
    table = node;
   }
   pthread_mutex_unlock(&mutex);
}

close(svr_fd);

pthread_mutex_destroy(&mutex);

return 0;
}
void * reader(void * args)
{
int ret = 0;
fd_set reader_fd;

while (true)
{
  struct SockFD * sock_list = 0;
  int max_fd = 0;
  pthread_mutex_lock(&mutex);
  struct SockFD * ptr = table;
  for (;ptr; ptr = ptr->next)
  {
   if (ptr->sock_fd > max_fd)
    max_fd = ptr->sock_fd;    
   FD_SET(ptr->sock_fd , &reader_fd);
   struct SockFD * node = (SockFD *)malloc(sizeof(SockFD));
   memset(node , 0x00 , sizeof(SockFD));  
   node->sock_fd = ptr->sock_fd;
   if (sock_list == 0)
    sock_list = node;
   else
   {
    node->next = sock_list;
    sock_list = node;
   }
  }
  pthread_mutex_unlock(&mutex);
  struct timeval timeout;
  timeout.tv_sec = 0;
  timeout.tv_usec = 50;  
  int ret = select(max_fd + 1 , &reader_fd , 0 , 0 , &timeout);
  if (ret > 0)
  {
   struct SockFD * ptr = sock_list;
   for (;ptr;ptr = ptr->next)
   {
    if (FD_ISSET(ptr->sock_fd , &reader_fd))
    {
     char buffer[256] = {0};
     if (read(ptr->sock_fd , buffer , 50) <= 0)
     {
      close(ptr->sock_fd);
      break;
     }
     printf("%s/n" , buffer);
    }
   }
  }
  
  struct SockFD * pNode = sock_list;
  while (pNode)
  {
   pNode = pNode->next;
   free(sock_list);
   sock_list = pNode;
  }
}
return 0;
}
void * writer(void * args)
{
int ret = 0;
fd_set writer_fd;
int max_fd = 0;
while (true)
{
  struct SockFD * sock_list = 0;
  
  pthread_mutex_lock(&mutex);
  struct SockFD * ptr = table;
  for (;ptr; ptr = ptr->next)
  {    
   if (ptr->sock_fd > max_fd)
    max_fd = ptr->sock_fd;
   FD_SET(ptr->sock_fd , &writer_fd);
   struct SockFD * node = (SockFD *)malloc(sizeof(SockFD));
   memset(node , 0x00 , sizeof(SockFD));  
   node->sock_fd = ptr->sock_fd;
   if (sock_list == 0)
    sock_list = node;
   else
   {
    node->next = sock_list;
    sock_list = node;
   }
  }
  pthread_mutex_unlock(&mutex);
  struct timeval timeout;
  timeout.tv_sec = 0;
  timeout.tv_usec = 50;  
  int ret = select(max_fd + 1 , 0 , &writer_fd , 0 , &timeout);
  if (ret > 0)
  {
   struct SockFD * ptr = sock_list;
   for (;ptr;ptr = ptr->next)
   {
    if (FD_ISSET(ptr->sock_fd , &writer_fd))
    {
     char buffer[256] = {0};
     sprintf(buffer , "response: from server.");
     if (write(ptr->sock_fd , buffer , 50) <= 0)
     {
      close(ptr->sock_fd);
      break;
     }
    }
   }
  }
  
  struct SockFD * pNode = sock_list;
  while (pNode)
  {
   pNode = pNode->next;
   free(sock_list);
   sock_list = pNode;
  }
}
return 0;
}
void * client(void * args)
{
int fd = 0;

if ((fd = socket(PF_INET , SOCK_STREAM , 0)) == -1)
{
  perror("socket");
  
  pthread_exit(&status);
}

struct sockaddr_in addr;
addr.sin_port = htons(SERVER_PORT);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
addr.sin_family = PF_INET;
if (connect(fd , (struct sockaddr *)&addr , sizeof(addr)) == -1)
{
  perror("connect");
  
  pthread_exit(&status);
}

char buffer[256] = {0};
sprintf(buffer , "request: from client.");
write(fd , buffer , 50);

memset(buffer , 0x00 , 256);
read(fd , buffer , 50);

printf("%s/n" , buffer);

close(fd);

return 0;
}

int main(int argc , char ** argv)
{
pthread_t svr_tid = 0;
pthread_t reader_tid = 0;
pthread_t writer_tid = 0;
pthread_t clt_tid1 = 0;
pthread_t clt_tid2 = 0;

printf("starting server....../n");
if (pthread_create(&svr_tid , 0 , server , 0) != 0)
{
  perror("pthread_create");
  
  return -1;
}

if (pthread_create(&reader_tid , 0 , reader , 0) != 0)
{
  perror("pthread_create");
  
  return -1;
}

if (pthread_create(&writer_tid , 0 , writer , 0) != 0)
{
  perror("pthread_create");
  
  return -1;
}

sleep(5);

printf("starting client....../n");

if (pthread_create(&clt_tid1 , 0 , client , 0) != 0)
{
  perror("pthread_create");
  
  return -1;
}
if (pthread_create(&clt_tid2 , 0 , client , 0) != 0)
{
  perror("pthread_create");
  
  return -1;
}
pthread_join(svr_tid , 0);
pthread_join(reader_tid , 0);
pthread_join(writer_tid , 0);
pthread_join(clt_tid1 , 0);
pthread_join(clt_tid2 , 0);
  
return 0;
}