poll epoll简单的回显服务器

1.poll io服务器(单线程处理所有请求)

server.c

#include <stdio.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>
#include <strings.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <pthread.h>
#include  <unistd.h>
#include  <arpa/inet.h>       /* inet(3) functions */
#include <poll.h> /* poll function */
#include <limits.h>
#include "pollio_server.h"

static struct pollfd client_fds[MAX_SELECT_CLIENT_NUM] = {0};
static reg_rcv_handle_call_back callbackfunc = NULL;
static int server_create(int port);
static void *poll_loop(void *arg);
/*****************************************
 *func:server_init
 *describe:初始化服务器端
 *para: port 端口号
 *return:成功则返回0,error则返回RET_VAL_FAILED
 *****************************************/
int server_init(const int port, const reg_rcv_handle_call_back func)
{
    int cnt = 10;
    static int ret_fd = -1;
    int ret;
    for (int i = 0; i < MAX_SELECT_CLIENT_NUM; i++)
    {
        client_fds[i].fd=-1;
    }
    while (cnt--)
    {
        ret_fd = server_create(port);
        if (RET_VAL_FAILED != ret_fd)
        {
            if (NULL == callbackfunc)
                callbackfunc = func;
            break;
        }
        usleep(100 * 1000);
    }
    if (ret_fd < 0)
    {
        return RET_VAL_FAILED;
    }
    cnt = 10;
    while (cnt--)
    {
        pthread_t loop_thread_id;
        ret = pthread_create(&loop_thread_id, NULL, poll_loop, &ret_fd);
        if (0 == ret)
        {
            pthread_detach(loop_thread_id);
            printf("init done ,wait client connect...\n");
            return RET_VAL_SUCCESS;
        }
    }
    return RET_VAL_FAILED;
}

/*****************************************
 *func:server_create
 *describe:创建监听的fd
 *para: port 端口号
 *return: 成功则返回监听的fd,error则返回RET_VAL_FAILED
 *****************************************/
int server_create(int in_port)
{
    struct addrinfo hints;
    struct addrinfo *result, *rp;
    int server_fd, retval;
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;     // Return IPv4 and IPv6 choices.
    hints.ai_socktype = SOCK_STREAM; // We want a TCP socket.
    hints.ai_flags = AI_PASSIVE;     // All interfaces.
    char port[16]={0};
    snprintf(port,sizeof(port),"%d",in_port);
    //数填写的套接口地址结构,port可以是http ftp字符
    retval = getaddrinfo(NULL, port, &hints, &result);
    if (retval != 0)
    {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retval));
        return RET_VAL_FAILED;
    }
    for (rp = result; rp != NULL; rp = rp->ai_next)
    {
        server_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (server_fd == RET_VAL_FAILED)
            continue;

        ////设置端口复用,防止被占用,服务器退出时再次绑定不会影响再次绑定
        int opt = 1;
        if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(int)) < 0)
        {
            printf(" set server_fd option SO_REUSEADDR error !");
              goto failed;
        }
        //bind soucket
        retval = bind(server_fd, rp->ai_addr, rp->ai_addrlen);
        if (retval == 0)
        {
            // We managed to bind successfully!
            break;
        }
        goto failed;
    }
    if (rp == NULL)
    {
        fprintf(stderr, "server_fd could not  bind\n");
          goto failed;
    }
    freeaddrinfo(result);
    //设置不阻塞模式
    int flags, s;
    flags = fcntl(server_fd, F_GETFL, 0);
    if (flags == RET_VAL_FAILED)
    {
        perror("server_fd fcntl set error ,F_GETFL\n");
          goto failed;
    }

    flags |= O_NONBLOCK;
    s = fcntl(server_fd, F_SETFL, flags);
    if (s == RET_VAL_FAILED)
    {
        perror("server_fd fcntl set error F_SETFL\n");
       goto failed;
    }
    //绑定端口号
    retval = listen(server_fd, SOMAXCONN);
    if (retval == RET_VAL_FAILED)
    {
        perror("server_fd listen error\n");
        goto failed;
    }
    client_fds[0].fd=server_fd;//监听fd
    client_fds[0].events = POLLRDNORM;
    return server_fd;
failed:
    close(server_fd);
    return RET_VAL_FAILED;
}

void *poll_loop(void *arg)
{
    int listen_fd = *((int *)arg);
    int max_fd = 0;
    int retval;
    int wait_timeout_ms=1000;//1s
    //select多路复用
    while (1)
    {
        max_fd = listen_fd;
        for (int i = 1; i < MAX_SELECT_CLIENT_NUM; i++)
        {
            if (client_fds[i].fd > 0)
            {
                if (max_fd <= client_fds[i].fd)
                {
                    max_fd = client_fds[i].fd;
                }
            }
        }
        retval = poll(client_fds,max_fd+1,wait_timeout_ms);
        if (retval > 0)
        {
            if ((client_fds[0].revents)&POLLRDNORM) //有新的客户端连接
            {
                struct sockaddr_in client_address;
                socklen_t address_len;
                int client_sock_fd = accept(listen_fd, (struct sockaddr *)&client_address, &address_len);
                if (client_sock_fd > 0)
                {
                    int flags = RET_VAL_FAILED;
                    //一个客户端到来分配一个fd,超过CLI_NUM以后跳出for循环,flags重新被赋值为RET_VAL_FAILED
                    for (int i = 1; i < MAX_SELECT_CLIENT_NUM; i++)
                    {
                        if (client_fds[i].fd <= 0)
                        {
                            flags = i;
                            client_fds[i].fd = client_sock_fd;
                            client_fds[i].events= POLLRDNORM;
                            client_fds[i].revents = 0;//目前还没有任何事件返回,置为零
                            break;
                        }
                    }
                    if (flags != RET_VAL_FAILED)
                    {
                        printf("new user client[%d]=%d add sucessfully!\n", flags, client_sock_fd);
                    }
                    else //flags=RET_VAL_FAILED
                    {
                        printf("the client nums is more than %d, can't login.close now!\n", MAX_SELECT_CLIENT_NUM);
                        close(client_sock_fd);
                    }
                }
            }
            else
            {
                //deal with the message
                for (int i = 1; i < MAX_SELECT_CLIENT_NUM; i++)
                {

                        if ((client_fds[i].revents)&POLLRDNORM)
                        {
                            char rcv_buff[MAX_RCV_BUFF_SIZE] = {0};
                            int len = recv(client_fds[i].fd, rcv_buff, MAX_RCV_BUFF_SIZE, MSG_DONTWAIT);
                            if (len > 0)
                            {
                                int send_len = send(client_fds[i].fd, rcv_buff, len, MSG_DONTWAIT);
                                printf("message form client[%d]=%d,rcv len%d,send_len=%d\n", i, client_fds[i].fd, len, send_len);
                                if (NULL != callbackfunc)
                                    callbackfunc(client_fds[i].fd, rcv_buff, len);
                                continue;
                            }
                            else if (len <= 0)
                            {
                                if(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
                                {
                                    continue;
                                }
                                close(client_fds[i].fd);
                                client_fds[i].fd = -1;
                                if (0 == len)
                                {
                                    printf("clien[%d] exit by itself!bye\n", i);
                                }
                                else
                                {
                                    //printf("clien[%d] is error!\n", i);
                                }
                            }
                        }
                    
                }
            }
        }
        if (retval < 0)
        {
            printf("poll error:%s\n", strerror(errno));
            continue;
        }
        else if (0 == retval)
        {
            //printf("poll  timeout!\n");
            continue;
        }
    }
}

void get_all_client(int out_clients[], const int size)
{
    if (size > MAX_SELECT_CLIENT_NUM)
    {
        for (int i = 0; i < MAX_SELECT_CLIENT_NUM; i++)
        {
            out_clients[i] = client_fds[i].fd;
        }
    }
    else
    {
        for (int i = 0; i < size; i++)
        {
            out_clients[i] = client_fds[i].fd;
        }
    }
}

server.h

#ifndef _pollio_server_H_
#define _pollio_server_H_
#ifdef __cplusplus 
extern "C"
{
#endif
#ifndef  RET_VAL_SUCCESS 
#define  RET_VAL_SUCCESS (0)
#endif
#ifndef  RET_VAL_FAILED
#define  RET_VAL_FAILED (-1)
#endif
#ifndef  MAX_SELECT_CLIENT_NUM
#define  MAX_SELECT_CLIENT_NUM (50200)//数量无限制
#endif
#ifndef  MAX_RCV_BUFF_SIZE
#define  MAX_RCV_BUFF_SIZE (4096*100)
#endif
typedef struct _client_info_t
{
    int fd;
    int login_id;
}client_info_t;
typedef int (*reg_rcv_handle_call_back)(const int fd,const void *data,const int data_len);
/*****************************************
 *func:server_init
 *describe:初始化服务器端
 *para: port 端口号
 *return:成功则返回0,error则返回-1
 *****************************************/
int server_init(const int port,const reg_rcv_handle_call_back func);
void get_all_client(int out_clients[],const int size);

#ifdef __cplusplus
}
#endif
#endif

main.c

#include <stdio.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>
#include <strings.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <pthread.h>
#include "pollio_server.h"
int sysUsecTime(char *pTime)
{
 struct timeval tv;
 struct timezone tz;
 struct tm *p;
 gettimeofday(&tv, &tz);
 p = localtime(&tv.tv_sec);
 sprintf(pTime, "%04d-%02d-%02d-%02d:%02d:%02d:.%06ld", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, tv.tv_usec);
 return 0;
}

int handle_call_back(const int fd,const void *data,const int data_len)
{
  static int cat_fd=5;
  if(cat_fd==fd)
 {
   char pTime[64]={0};
   sysUsecTime(pTime);
   printf("[%s]:fd=%d,len=%d\n",pTime,fd,data_len);
 }

}
int main(int argc, char **argv)
{
    server_init(11111, handle_call_back);
    int out_clients[1024]={0};

    while (1)
    {
        #if 0
        get_all_client(out_clients, 1024);
        int print_flag=-1;
 
        for (int i = 0; i < 1024; i++)
        {
            if (out_clients[i] > 0)
            {
                if(print_flag<0)
                    printf("client:");
                print_flag=1;
                printf("client[%d]=%d ",i ,out_clients[i]);
            }
        }
           if(print_flag>0)
        printf("\n");
        #endif
        sleep(5);
    }
}

 

2.epoll io 服务器(单线程)

#include <stdio.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/select.h>
#include <strings.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <pthread.h>
#include <unistd.h>
#include <arpa/inet.h> /* inet(3) functions */
#include <sys/epoll.h>
#include <limits.h>
#include "epollio_server.h"
#define MAX_EPOOL_EVENTS (1024)
static int client_fds[MAX_SELECT_CLIENT_NUM] = {0};
static reg_rcv_handle_call_back callbackfunc = NULL;
static int server_create(int port);
static int epoll_init(int listen_fd);
static void *epool_loop(void *arg);
/*****************************************
 *func:server_init
 *describe:初始化服务器端
 *para: port 端口号
 *return:成功则返回0,error则返回RET_VAL_FAILED
 *****************************************/
int server_init(const int port, const reg_rcv_handle_call_back func)
{
    int cnt = 10;
    static int ret_fd = -1;
    int ret;
    for (int i = 0; i < MAX_SELECT_CLIENT_NUM; i++)
    {
        client_fds[i] = -1;
    }
    while (cnt--)
    {
        ret_fd = server_create(port);
        if (RET_VAL_FAILED != ret_fd)
        {
            if (NULL == callbackfunc)
                callbackfunc = func;
            break;
        }
        usleep(100 * 1000);
    }
    if (ret_fd < 0)
    {
        return RET_VAL_FAILED;
    }
    cnt = 10;
    while (cnt--)
    {
        int ret =epoll_init(ret_fd);
        if (RET_VAL_FAILED != ret)
        {
            printf("init done ,wait client connect...\n");
            return RET_VAL_SUCCESS;
        }
        usleep(100 * 1000);
    }
    return RET_VAL_FAILED;
}

/*****************************************
 *func:server_create
 *describe:创建监听的fd
 *para: port 端口号
 *return: 成功则返回监听的fd,error则返回RET_VAL_FAILED
 *****************************************/
int server_create(int in_port)
{
    struct addrinfo hints;
    struct addrinfo *result, *rp;
    int server_fd, retval;
    memset(&hints, 0, sizeof(struct addrinfo));
    hints.ai_family = AF_UNSPEC;     // Return IPv4 and IPv6 choices.
    hints.ai_socktype = SOCK_STREAM; // We want a TCP socket.
    hints.ai_flags = AI_PASSIVE;     // All interfaces.
    char port[16] = {0};
    snprintf(port, sizeof(port), "%d", in_port);
    //数填写的套接口地址结构,port可以是http ftp字符
    retval = getaddrinfo(NULL, port, &hints, &result);
    if (retval != 0)
    {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(retval));
        return RET_VAL_FAILED;
    }
    for (rp = result; rp != NULL; rp = rp->ai_next)
    {
        server_fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
        if (server_fd == RET_VAL_FAILED)
            continue;

        ////设置端口复用,防止被占用,服务器退出时再次绑定不会影响再次绑定
        int opt = 1;
        if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (void *)&opt, sizeof(int)) < 0)
        {
            printf(" set server_fd option SO_REUSEADDR error !");
            goto failed;
        }
        //bind soucket
        retval = bind(server_fd, rp->ai_addr, rp->ai_addrlen);
        if (retval == 0)
        {
            // We managed to bind successfully!
            break;
        }
        goto failed;
    }
    if (rp == NULL)
    {
        fprintf(stderr, "server_fd could not  bind\n");
        goto failed;
    }
    freeaddrinfo(result);
    //设置不阻塞模式
    int flags, s;
    flags = fcntl(server_fd, F_GETFL, 0);
    if (flags == RET_VAL_FAILED)
    {
        perror("server_fd fcntl set error ,F_GETFL\n");
        goto failed;
    }

    flags |= O_NONBLOCK;
    s = fcntl(server_fd, F_SETFL, flags);
    if (s == RET_VAL_FAILED)
    {
        perror("server_fd fcntl set error F_SETFL\n");
        goto failed;
    }
    //绑定端口号
    retval = listen(server_fd, SOMAXCONN);
    if (retval == RET_VAL_FAILED)
    {
        perror("server_fd listen error\n");
        goto failed;
    }
    client_fds[0] = server_fd; //监听fd
    return server_fd;
failed:
    close(server_fd);
    return RET_VAL_FAILED;
}

int epoll_init(int listen_fd)
{
    static int listenfd=0;
    listenfd=listen_fd;
    int cnt = 10;
    int ret = -1;
    while (cnt--)
    {
        pthread_t loop_thread_id;
        ret = pthread_create(&loop_thread_id, NULL, epool_loop, &listenfd);
        if (0 == ret)
        {
            pthread_detach(loop_thread_id);
            return RET_VAL_SUCCESS;
        }
        usleep(10 * 1000);
    }
    return RET_VAL_FAILED;
}
void *epool_loop(void *arg)
{
    int listen_fd = *((int *)arg);
    int max_fd = 0;
    int retval;
    int wait_timeout_ms = 1000; //1s

    int ret = -1;
    int efd;
    struct epoll_event event;
    struct epoll_event *events;
    //除了参数size被忽略外,此函数和epoll_create完全相同
    efd = epoll_create1(0);
    if (efd == -1)
    {
        perror("epoll_create error,exit");
            exit(-1);
    }
    event.data.fd = *((int *)arg);
    event.events = EPOLLIN | EPOLLET; //读入,边缘触发方式
    ret = epoll_ctl(efd, EPOLL_CTL_ADD, listen_fd, &event);
    if (ret == -1)
    {
        perror("epoll_ctl error,exit");
        exit(-1);
    }
    /* Buffer where events are returned */
    events = calloc(MAX_EPOOL_EVENTS, sizeof(event));
    //select多路复用
    while (1)
    {

        int n = 0, i = 0;
        n = epoll_wait(efd, events, MAX_EPOOL_EVENTS, -1);
        for (i = 0; i < n; i++)
        {
            if ((events[i].events & EPOLLIN))
            {
                if (listen_fd != events[i].data.fd)
                {
                    int len=-1;
                    do
                    {
                        char rcv_buff[MAX_RCV_BUFF_SIZE] = {0};
                        len = recv(events[i].data.fd, rcv_buff, MAX_RCV_BUFF_SIZE, MSG_DONTWAIT);
                        if (len > 0)
                        {
                            int send_len = send(events[i].data.fd, rcv_buff, len, MSG_DONTWAIT);
                            //printf("message form client=%d,rcv len%d,send_len=%d\n", events[i].data.fd, len, send_len);
                            if (NULL != callbackfunc)
                                callbackfunc(events[i].data.fd, rcv_buff, len);
                            continue;
                        }
                        else if (len <= 0)
                        {
                            if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
                            {
                                continue;
                            }
                            close(events[i].data.fd);
                            for(int k=0;k<MAX_SELECT_CLIENT_NUM;k++)
                            {
                                if( client_fds[k]==events[i].data.fd)
                                {
                                    client_fds[k]=-1;
                                    break;
                                }
                            }
                            if (0 == len)
                            {
                                printf("clien[%d] exit by itself!bye\n", events[i].data.fd);
                            }
                            else
                            {
                                printf("clien[%d] is error!\n", events[i].data.fd);
                            }
                            events[i].data.fd = -1;
                        }

                    } while (len==MAX_RCV_BUFF_SIZE);
                }
                else
                {
                    struct sockaddr in_addr;
                    socklen_t in_len;
                    int infd;
                    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
                    in_len = sizeof in_addr;
                    infd = accept(listen_fd, &in_addr, &in_len);
                    if (infd == -1)
                    {
                        if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
                        {
                            /* We have processed all incoming connections. */
                            continue;
                        }
                        else
                        {
                            perror("accept error\n");
                            continue;
                        }
                    }
                    //将地址转化为主机名或者服务名
                    ret = getnameinfo(&in_addr, in_len, hbuf, sizeof hbuf, sbuf, sizeof sbuf, NI_NUMERICHOST | NI_NUMERICSERV); //主机地址和服务地址,flag参数:以数字名返回
                    if (ret == 0)
                    {
                        printf("Accepted connection on descriptor %d (host=%s, port=%s)\n", infd, hbuf, sbuf);
                    }
                    else if (ret == -1)
                    {
                        perror("accept:getnameinfo error \n");
                        close(infd);
                        continue;
                    }
                    event.data.fd = infd;
                    event.events = EPOLLIN | EPOLLET;
                    ret = epoll_ctl(efd, EPOLL_CTL_ADD, infd, &event);
                    if (ret == -1)
                    {
                        perror("epoll_ctl error ,");
                        close(infd);
                        continue;
                    }
                    for(int k=0;k<MAX_SELECT_CLIENT_NUM;k++)
                    {
                        if(-1== client_fds[k])
                        {
                            client_fds[k]=infd;
                            break;
                        }
                       
                    }
                }
            }
            else if ((events[i].events & EPOLLERR) || (events[i].events & EPOLLHUP))
            {
                /* An error has occured on this fd, or the socket is not
                ready for reading (why were we notified then?) */
                fprintf(stderr, "epoll error\n");
                close(events[i].data.fd);
                for(int k=0;k<MAX_SELECT_CLIENT_NUM;k++)
                {
                    if( client_fds[k]==events[i].data.fd)
                    {
                        client_fds[k]=-1;
                        break;
                    }
                }
                continue;
            }
        }
    }
    free(events);
    close(listen_fd);
}

void get_all_client(int out_clients[], const int size)
{
    if (size > MAX_SELECT_CLIENT_NUM)
    {
        for (int i = 0; i < MAX_SELECT_CLIENT_NUM; i++)
        {
            out_clients[i] = client_fds[i];
        }
    }
    else
    {
        for (int i = 0; i < size; i++)
        {
            out_clients[i] = client_fds[i];
        }
    }
}

3.测试客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/select.h>
#include <strings.h>
#include <string.h>
#define MAXLINE 4096*100
int sockfd[1000] = {0};
char recvLine[MAXLINE], sendLine[MAXLINE];
void *recv_func(void *arg)
{
    fd_set ser_fdset;
    int max_fd =2;
    struct timeval mytime;
    while (1)
    {
         max_fd =2;
        FD_ZERO(&ser_fdset);
        for (int i = 0; i < 1000; i++)
        {
            if (sockfd[i] > 0)
            {
                FD_SET(sockfd[i], &ser_fdset);
                if(sockfd[i]>max_fd)
                {
                    max_fd=sockfd[i];
                }
                
            }
            
        }
        mytime.tv_sec = 1;
        int ret = select(max_fd+1, &ser_fdset, NULL, NULL, &mytime);
        if (ret < 0)
        {
            perror("select failure\n");
            continue;
        }
        else if (ret == 0)
        {
            //printf("time out! \n");
            continue;
        }
        else
        {
            for (int i = 0; i < 1000; i++)
            {
                if (FD_ISSET(sockfd[i], &ser_fdset))
                {
                    int len = -1;
                    memset(recvLine, 0, sizeof(recvLine));
                    if (sockfd[i] > 0)
                    {
                        len = recv(sockfd[i], recvLine, sizeof(recvLine), MSG_DONTWAIT);
                        printf("recv len=%d\n", len);
                    }
                }
            }
        }
    }
}
int main(int argc, char **argv)
{
    int n;
    struct sockaddr_in servaddr;
    while (1)
    {
        static int i = 0;
        if ((sockfd[i] = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
            printf("create socket error: %s(errno: %d)\n", strerror(errno), errno);
            return 0;
        }
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(11111);
        if (inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr) <= 0)
        {
            printf("inet_pton error for 127.0.0.1\n");
            return 0;
        }
        if (connect(sockfd[i], (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        {
            //客户端需要调用connect()连接服务器,connect和bind的参数形式一致,区别在于bind的参数是自己的地址,而connect的参数是对方的地址。connect()成功返回0,出错返回-1
            printf("connect error: %s(errno: %d)\n", strerror(errno), errno);
            sockfd[i]=-1;
        }
        usleep(1 * 100);
        i++;
        if (i >= 1000)
            break;
    }
    printf("send msg to server: \n");
    memset(sendLine, 0, sizeof(sendLine));
    for (int i = 0; i < MAXLINE; i++)
    {
        sendLine[i] = 'c';
    }

    sendLine[MAXLINE - 1] = 0;
    int len = strlen(sendLine);
    pthread_t recv_pth;
    pthread_create(&recv_pth, NULL, recv_func, NULL);
    pthread_detach(recv_pth);
    while (1)
    {
        for (int i = 0; i < 1000; i++)
        {

            if (sockfd[i] > 0)
            {
            
                int ret = send(sockfd[i], sendLine, len, MSG_DONTWAIT);
                if (ret < 0)
                {
                    printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
                }
                printf("send len=%d\n", ret);
                usleep(3);
            }
            
        }
    }
    for (int i = 0; i < 1000; i++)
        close(sockfd[i]);
    return 0;
}

测试结果:

1000个客户端连接,每3微秒发100K数据

100个客户端连接,每3微秒发100K数据

 

 

 

posted @ 2021-04-24 22:45  jest549  阅读(86)  评论(0编辑  收藏  举报