Linux网络编程使用poll函数建立TCP C/S模型(C++实现)

服务端代码:
感觉和select区别不大,而且不能像select那样跨平台

/*************************************************************************
    > File Name: server.cpp
    > Author: chencj
    > Mail: 1378755306@qq.com 
    > Created Time: 2020年08月05日 星期三 09时49分18秒
 ************************************************************************/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdlib>
#include <poll.h>

const int N  = 128;
const int Max_Size = 1024;
static int Maxi = 0;
void sys_err(std::string msg)  //出错函数
{
    perror(msg.c_str());
    exit(1);
}
class Server{
private:
    int num;  //记录连接客户端的数量
    int lfd,cfd;  //监听套接字  通信套接字
    struct sockaddr_in server_addr,client_addr;  //服务端 客户端地址结构
    struct pollfd pfd[Max_Size];  //监听集合
    char buf[N];
public:
    Server():num(0){}
    ~Server(){}
    void CreateSock(); //建立套接字
    void CreateAddr(const char *,const char *);  //设置地址结构
    void Listen_Bind();  //绑定 监听
    void solve();  //通信
};
void Server::CreateSock()
{
    lfd = socket(AF_INET,SOCK_STREAM,0);
    if(lfd == -1) sys_err("socket error\n");
}
void Server::CreateAddr(const char *IP,const char* PORT)
{
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_addr.s_addr = inet_addr(IP);
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(atoi(PORT));
}
void Server::Listen_Bind()
{
    int vel = 1;
    setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,(void*)&vel,sizeof(vel));
    if(bind(lfd,(struct sockaddr*)&server_addr,sizeof(server_addr)) == -1)
    sys_err("bind error\n");
    if(listen(lfd,N) == -1)
    sys_err("listen error\n");
}
void Server::solve()
{
    socklen_t clen = sizeof(client_addr);
    pfd[0].fd = lfd;
    pfd[0].events = POLLIN;
    for(int i=1;i<Max_Size;i++)
    pfd[i].fd = -1;
    while(1)
    {
        int ret;
        ret = poll(pfd,Maxi+1,-1);
        if(ret < 0) sys_err("poll error\n");
        else if(ret > 0)
        {
            if(pfd[0].revents & POLLIN) {
                cfd = accept(lfd,(struct sockaddr*)&client_addr,&clen);
                if(cfd == -1) sys_err("accept error\n");
                ++num;
                printf("[ip : %s--port : %d]--%d  connect\n",inet_ntoa(client_addr.sin_addr),
                    ntohs(client_addr.sin_port),num);
                if(num == Max_Size) sys_err("over Max_Size\n");
                for(int i=1;i<Max_Size;i++) {
                    if(pfd[i].fd == -1) {
                        pfd[i].fd = cfd;
                        pfd[i].events = POLLIN;
                        if(i > Maxi) Maxi = i;
                        break;
                    }
                }
                if(ret == 1) continue;
            }

            for(int i=1;i<=Maxi;i++)
            {
                if(pfd[i].fd == -1) continue;

                if(pfd[i].revents & POLLIN) {
                    memset(buf,'\0',sizeof(buf));
                    int data = read(pfd[i].fd,buf,sizeof(buf));
                    if(data == -1) sys_err("read error\n");
                    if(data == 0) {
                        pfd[i].fd = -1;
                        close(pfd[i].fd);
                        printf("One Disconnect----%d client remains\n",--num);
                    }
                    else {
                        printf("[ip : %s--port : %d]--data : %s\n",inet_ntoa(client_addr.sin_addr),
                            ntohs(client_addr.sin_port),buf);
                        write(pfd[i].fd,"Accept",7);
                    }
                }
            }
        }
    }
    close(lfd);
}
int main(int argc, char const *argv[])
{
    if(argc < 3) sys_err("input error\n");
    Server T = Server();  //一个server对象
    T.CreateSock();
    T.CreateAddr(argv[1],argv[2]);
    T.Listen_Bind();
    T.solve();
    return 0;
}

客户端代码:

/*************************************************************************
    > File Name: client.cpp
    > Author: chencj
    > Mail: 1378755306@qq.com 
    > Created Time: 2020年08月05日 星期三 09时49分28秒
 ************************************************************************/

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>

const int N = 128;
void sys_err(std::string msg)
{
    perror(msg.c_str());
    exit(1);
}
class Client{
private:
    int sockfd;
    struct sockaddr_in client_addr;
    char buf[N],recv_buf[N];
public:
    Client(){}
    ~Client(){};
    void CreateSock();
    void CreateAddr(const char*,const char*);
    void slove();
};
void Client::CreateSock()
{
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd == -1) sys_err("socket error\n");
}
void Client::CreateAddr(const char *IP,const char *PORT)
{
    bzero(&client_addr,sizeof(client_addr));
    client_addr.sin_addr.s_addr = inet_addr(IP);
    client_addr.sin_family = AF_INET;
    client_addr.sin_port = htons(atoi(PORT));
}
void Client::slove()
{
    if(connect(sockfd,(struct sockaddr*)&client_addr,sizeof(client_addr)) == -1)
    sys_err("connect error\n");
    std::cout<<"------Connect---------\n";
    memset(buf,'\0',sizeof(buf));
    while(fgets(buf,N,stdin) != NULL)
    {
        write(sockfd,buf,sizeof(buf));
        memset(recv_buf,'\0',sizeof(recv_buf));
        read(sockfd,recv_buf,sizeof(recv_buf));
        std::cout<<recv_buf<<std::endl;
        if(memcmp("###",buf,3) == 0) {
            std::cout<<"------Disconnect------"<<std::endl;
            break;
        }
        memset(buf,'\0',sizeof(buf));
    }
    close(sockfd);
}
int main(int argc, char const *argv[])
{
    Client T = Client();
    T.CreateSock();
    T.CreateAddr(argv[1],argv[2]);
    T.slove();
    return 0;
}

测试结果
结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

译制片~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值