epoll 模型原理详解以及实例(5)

send_size = send(connfd, p, remain_size, flag);
      if (nSentSize < 0)
      {
        if ((errno == EAGAIN) || (errno == EWOULDBLOCK) || (errno == EINTR))
        {
            continue;
        }
        else
        {
            len -= remain_size;
            return false;
        }
      }

p += send_size;
      remain_size -= send_size;
  }while(remain_size > 0);

return true;
}10 epoll 实现服务器和客户端例子
最后我们用C++实现一个简单的客户端回射,所用到的代码文件是

net.h  server.cpp  client.cpp服务器端:epoll实现的,干两件事分别为:1.等待客户端的链接,2.接收来自客户端的数据并且回射;

客户端:select实现,干两件事为:1.等待键盘输入,2.发送数据到服务器端并且接收服务器端回射的数据;

/***********
net.h
***********/
#include <stdio.h>

#ifndef _NET_H
#define _NET_H

#include <iostream>
#include <vector>
#include <algorithm>

#include <stdio.h>
#include <sys/types.h>
#include <sys/epoll.h>  //epoll ways file
#include <sys/socket.h>
#include <fcntl.h>    //block and noblock

#include <stdlib.h>
#include <error.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string.h>
#include <signal.h>

using namespace std;


#define hand_error(msg) do{perror(msg); exit(EXIT_FAILURE);}while(0)
#endif


/***********
server.c
***********/
#include "net.h"
#define MAX_EVENTS 10000

int setblock(int sock)
{
    int ret =  fcntl(sock, F_SETFL, 0);
    if (ret < 0 )
        hand_error("setblock");
    return 0;
}
int setnoblock(int sock)  //设置非阻塞模式
{
    int ret = fcntl(sock,  F_SETFL, O_NONBLOCK );
    if(ret < 0)
        hand_error("setnoblock");
    return 0;
}

int main()
{
    signal(SIGPIPE,SIG_IGN);
  int listenfd;
    listenfd = socket( AF_INET, SOCK_STREAM,0 );  //create a socket stream
    if( listenfd < 0 )
        hand_error( "socket_create");
    setnoblock(listenfd);
    int on = 1;
    if( setsockopt( listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))< 0)
        hand_error("setsockopt");

struct sockaddr_in my_addr;
    memset(&my_addr, 0, sizeof(my_addr));
    my_addr.sin_family = AF_INET;
    my_addr.sin_port = htons(18000);  //here is host  sequeue
    my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

if( bind( listenfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
        hand_error("bind");

int lisId = listen(listenfd, SOMAXCONN);
    if( lisId < 0)  //LISTEN
        hand_error("listen");

struct sockaddr_in peer_addr;  //用来 save client addr
    socklen_t peerlen; 
    //下面是一些初始化,都是关于epoll的。
    vector<int> clients;
    int count = 0;
    int cli_sock = 0;
    int epfd = 0;  //epoll 的文件描述符
    int ret_events;  //epoll_wait()的返回值
  struct epoll_event ev_remov, ev, events[MAX_EVENTS];  //events 用来存放从内核读取的的事件
    ev.events = EPOLLET | EPOLLIN;  //边缘方式触发
    ev.data.fd = listenfd;

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/07056860132b8a0bd306cfbb0a535cbb.html