linux服务器模型--select多路复用2011

本文详细介绍了一个基于TCP协议的多客户端并发服务器的实现过程。该服务器能够同时处理多个客户端的连接请求,通过使用select机制监测读写事件,并利用数组记录已连接的客户端套接字。文章深入探讨了socket编程、监听套接字设置、客户端连接接受、数据接收及发送等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

 

#include <SYS types.h>   
#include <SYS ioctl.h>
#include <SYS wait.h>   
#include <STDIO.H>   
#include <SYS socket.h>
#include <ERRNO.H>   
#include <STRING.H>   
#include <STDLIB.H> 
#include <SYS time.h>    
#include <UNISTD.H>   
#include <NETINET in.h>   
#include <SYS un.h>   

 

#define LISTEN_BACKLOGNUM 20
#define MAX_CONNECTED_NUM 20
#define NUM_SOCKFD 10
#define MAX_DATABUFFER_SIZE 200
int main(int argc, char **argv)
{
 char strdatabuffer1[MAX_DATABUFFER_SIZE];
 //char* strdatabuffer2;
 fd_set fdset_readfd;
 fd_set fdset_writefd;
 fd_set fdset_errorfd;
 int nmaxfds;
 int hListenSocketfd;
 int newclientsocketfd;
 unsigned long linit = 0;

 int arraysockfd[NUM_SOCKFD];
 linit = init_socket_listen(atoi(argv[1]), hListenSocketfd );
 if(linit < 0)
  exit(0);
 printf("server current states is listening...");
 FD_ZERO(&fdset_readfd);
 FD_ZERO(&fdset_writefd);
 FD_SET(hListenSocketfd, &fdset_readfd);
 FD_SET(hListenSocketfd, &fdset_writefd);
 FD_SET(hListenSocketfd, &fdset_errorfd)
  nmaxfds = hListenSocketfd;

 while(true)
 {
  int nselectresult;

        for(int ncount = 0; ncount < NUM_SOCKFD; ncount++)
  {
   if(arraysockfd[ncount] != 0)
   {
    FD_SET(arraysockfd[ncount], &fdset_readfd );
   }
   
  }
  timeval.tv_sec = 30;
  timeval.tv_usec =0;

  nselectresult = select(nmaxfds + 1, &fdset_readfd, &fdset_writefd, &fdset_errorfd, &timeval );
  if(nselectresult == -1 && fdset_errorfd == EINTR)
   continue;
  if(nselectresult < 0)
  {
   perror("select(nmaxfds + 1, &fdset_readfd, &fdset_writefd, &fdset_errorfd, NULL )");
   exit(1);
  
  }
  if(FD_ISSET(hListenSocketfd, &fdset_readfd))
  {
   struct sockaddr_in client_address;
    memset (&client_address, 0,  sizeof (client_address));
    int clienaddrlength = sizeof(client_address);
    newclientsocketfd = accept (hListenSocketfd, (struct sockaddr *)&client_address, &clienaddrlength);

    for(int i = 0 ; i < NUM_SOCKFD; i++)
    {
      if(arraysockfd[i] == 0)
     {
                      arraysockfd[i]  = newclientsocketfd;
       break;
    
     } 
 
    }
    if(newclientsocketfd > nmaxfds)
     nmaxfds = newclientsocketfd;

         // if(read(client_fd,buf,MAXDATASIZE)<0){  
    read(newclientsocketfd, strdatabuffer1, MAX_DATABUFFER_SIZE, 0);
    printf("receive a connection: %s\n",  strdatabuffer1);
    close(newclientsocketfd);
  }

  for(int i = 0 ; i < NUM_SOCKFD; i++)
  {
   if(FD_ISSET(arraysockfd[i] , &fdset_readfd))
   {
    int nrecvCnt = read(newclientsocketfd, strdatabuffer1, MAX_DATABUFFER_SIZE, 0);
    if(nrecvCnt <= 0)
    {
     printf("client[%d] close\n",i);
     close(arraysockfd[i]);
     FD_CLR(arraysockfd[i], &fdset_readfd);

     arraysockfd[i] = 0;

    
    }
    else
    {
     memset(&strdatabuffer1[nrecvCnt], '/0', 1);
     printf("client[%d] send:%s\n", i, strdatabuffer1);

    
    }   
   }
  }
 }
}

static unsigned long init_socket_listen(const int listen_port, int listensocket)
{
 int listensocketfd;
 struct sockaddr_in serversockaddr;
 listensocketfd = socket(AF_INET, SOCK_STREAM, 0);
 if(listensocketfd < 0)
 {
  perror("socket(AF_INET, SOCK_STREAM, 0)");
  return -1;
 }
 int optIndexVal = 1;
 setsockopt(listensocketfd, SOL_SOCKET,  SO_REUSEADDR, (char*)&optIndexVal, sizeof(optIndexVal));
 memset(&serversockaddr, 0, sizeof(serversockaddr));
 serversockaddr.sin_family = AF_INET;
    serversockaddr.sin_port = htons(listen_port);
 serversockaddr.sin_addr.s_addr=INADDR_ANY; 
 bzero(&(serversockaddr.sin_zero), 8);
 if(bind(listensocketfd, (struct sockaddr *)&serversockaddr, sizeof(serversockaddr)) < 0)
 {
  perror("bind(listensocketfd, (struct sockaddr *)&serversockaddr, sizeof(serversockaddr))");
  close(listensocketfd);
  exit(1);
 }
 printf("listen socket bind to the server port sucess!");

 if(listen(listensocketfd, LISTEN_BACKLOGNUM) < 0)
 {
  perror("listen(listensocketfd, LISTEN_BACKLOGNUM)");
  close(listensocketfd);
  exit(1);

 }

 listensocket = listensocketfd

 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值