ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android上利用epoll机制实现手机服务器?

2021-06-08 15:34:23  阅读:277  来源: 互联网

标签:std cout epoll sockfd 服务器 Android include events


废话不多数。先上代码。server.cpp

#include <jni.h>
#include <string>
#include <cmath>
#include <sys/epoll.h>
#include <iostream>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include "android/log.h"
#include "jni.h"
#include <pthread.h>

struct epoll_event ev, events[20];
#define LISTENQ 20
#define MAXLINE 5

int main(int argc, char *argv[]) {
    int i, maxi, listenfd, connfd, sockfd, myepfd, nfds, portnumber;
    ssize_t n;
    char line[MAXLINE];
    socklen_t clilen;
    myepfd = epoll_create(58);
    portnumber = 8888;
    struct sockaddr_in clientaddr;
    struct sockaddr_in serveraddr;
    listenfd = socket(AF_INET, SOCK_STREAM, 0);
    std::cout << "文件描述符为" + std::to_string(listenfd) << std::endl;
    if (listenfd < 0) {
        std::cout << "打开文件错误" + std::to_string(listenfd) << std::endl;
    }
    ev.data.fd = listenfd;
    //设置要处理的事件类型
    ev.events = EPOLLIN | EPOLLOUT;
    epoll_ctl(myepfd, EPOLL_CTL_ADD, listenfd, &ev);

    serveraddr.sin_family = AF_INET;
    char *local_addr = "10.6.25.153";
    inet_aton(local_addr, &(serveraddr.sin_addr));//htons(portnumber);
    serveraddr.sin_port = htons(portnumber);
    bind(listenfd, (sockaddr *) &serveraddr, sizeof(serveraddr));
    listen(listenfd, LISTENQ);


    for (;;) {
        //等待epoll事件的发生

        int nfds = epoll_wait(myepfd, events, 20, -1);
        std::cout << "addr(obj2.pszTestStr) is: " + std::to_string(nfds) << std::endl;
        for (int i = 0; i < nfds; ++i) {
            if (events[i].data.fd == listenfd)//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口,建立新的连接。

            {
                connfd = accept(listenfd, (sockaddr *) &clientaddr, &clilen);
                if (connfd < 0) {
                    std::cout << "connfd<0" << std::endl;
                    exit(1);
                }
                char *str = inet_ntoa(clientaddr.sin_addr);
                std::cout << "accapt a connection from " << str << std::endl;
                //设置用于读操作的文件描述符
                ev.data.fd = connfd;
                //设置用于注测的读操作事件
                ev.events = EPOLLIN | EPOLLET;
                //注册ev
                epoll_ctl(myepfd, EPOLL_CTL_ADD, connfd, &ev);
            } else if (events[i].events & EPOLLIN)//如果是已经连接的用户,并且收到数据,那么进行读入。

            {
                std::cout << "EPOLLIN" << std::endl;
                if ((sockfd = events[i].data.fd) < 0)
                    continue;
                if ((n = read(sockfd, line, MAXLINE)) < 0) {
                    if (errno == ECONNRESET) {
                        close(sockfd);
                        events[i].data.fd = -1;
                    } else
                        std::cout << "readline error" << std::endl;
                } else if (n == 0) {
                    close(sockfd);
                    events[i].data.fd = -1;
                }
                line[n] = '/0';
                std::cout << "read " << line << std::endl;
                //设置用于写操作的文件描述符

                ev.data.fd = sockfd;
                //设置用于注测的写操作事件

                ev.events = EPOLLOUT | EPOLLET;
                //修改sockfd上要处理的事件为EPOLLOUT

                epoll_ctl(myepfd, EPOLL_CTL_MOD, sockfd, &ev);

            } else if (events[i].events & EPOLLOUT) // 如果有数据发送

            {
                sockfd = events[i].data.fd;
                write(sockfd, line, n);
                //设置用于读操作的文件描述符

                ev.data.fd = sockfd;
                //设置用于注测的读操作事件

                ev.events = EPOLLIN | EPOLLET;
                //修改sockfd上要处理的事件为EPOLIN

                epoll_ctl(myepfd, EPOLL_CTL_MOD, sockfd, &ev);
            }
        }
    }

    return 0;
}

以上为server的代码,我们现在把它编译为能够运行在android手机上。这里要注意下。监听的ip要为自己手机的实际ip地址。可以通过ifconfig查看。如果用本机的“127.0.0.1”会监听不成功。利用android studio的cmake编译系统能够方便的编译。这里我把我的cmakeList贴出来。

add_executable(
        server
        server.cpp
)

另外app的build.gradle 文件中,配置支持c++。

 externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
            }
        }

实际上主要就是这一句话。现在看下效果。
首先看下服务运行。注意server文件要不能拷贝到sdrcard这类目录运行,因为没有运行权限。
在这里插入图片描述
然后另外一台电脑通过telnet 可以进行socket通信。
在这里插入图片描述
输入字符对应android服务器就可以读取出来了
在这里插入图片描述
大家可以看到,连接建立的时候epoll_wait 会返回,在epoll_event 中我们能够相应的事件。具体epoll的实现原理不细讲了,大家最好还是通过代码来熟悉相关原理比较好。

标签:std,cout,epoll,sockfd,服务器,Android,include,events
来源: https://blog.csdn.net/d_o_n_g2/article/details/117702444

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有