Linux下网络编程-简易poll服务器和客户端

Linux下网络编程-简易poll服务器和客户端

简易poll服务器:
cpp 复制代码
//编译命令:g++ -g xxx.cpp -o xxx
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <poll.h>

int main(int argc, char *argv[])
{
	// 1.创建套接字
    int serv_sock=socket(PF_INET, SOCK_STREAM, 0);
    struct sockaddr_in serv_adr;
	memset(&serv_adr, 0, sizeof(serv_adr));
	serv_adr.sin_family=AF_INET;
	serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
	serv_adr.sin_port=htons(atoi(argv[1]));
	
	// 2. 绑定 ip, port
    if(bind(serv_sock, (struct sockaddr*) &serv_adr, sizeof(serv_adr))==-1)
		error_handling("bind() error");
	// 3. 监听
	if(listen(serv_sock, 5)==-1)
		error_handling("listen() error");

     //4 等待连接->循环
    //检测->都缓冲区,委托内核去处理
    //数据初始化,创建自定义得文件描述集
    struct pollfd fds[1024];
    //初始化
    for(int i=0;i<1024;i++)
    {
        fds[i].fd=-1;
        fds[i].events=POLLIN;
    }
    fds[0].fd=serv_sock;

    int maxfd=0;
    while (1) 
    {
        //委托内核检测
        if(poll(fds, maxfd+1, -1)==-1)
        {
            perror("select");
            exit(0);
        }

        //检测的度缓冲区有变化
        //有新连接
        if(fds[0].revents&POLLIN)
        {
            // 接收连接请求
            struct sockaddr_in sockcli;
            socklen_t len = sizeof(sockcli);
            // 这个accept是不会阻塞的
            int connfd = accept(serv_sock, (struct sockaddr*)&sockcli, &len);
            //委托内核检测connfd的读缓冲区
            int i;
            for(i=0;i<1024;i++)
            {
                if(fds[i].fd==-1)
                {
                    fds[i].fd=connfd;
                    break;
                }
            }
            maxfd=i>maxfd?i:maxfd;
        }
        //通信。有客户端发送数据过来
        for(int i=1;i<=maxfd;i++)
        {
            //如果在集合中,说明都缓冲区有数据
            if(fds[i].revents&POLLIN)
            {
                char buf[128];
                int ret = read(fds[i].fd, buf, sizeof(buf));
                if(ret == -1)
                {
                    perror("read");
                    exit(0);
                }
                else if(ret == 0)
                {
                    printf("对方已经关闭了连接...\n");
                    close(fds[i].fd);
                    fds[i].fd = -1;
                }
                else
                {
                    printf("客户端say: %s\n", buf);
                    write(fds[i].fd, buf, strlen(buf)+1);
                }
            }
        }
    }
    close(serv_sock);
    return 0;
}
简易客户端:
cpp 复制代码
//编译命令:g++ -g xxx.cpp -o xxx
#include <netinet/in.h>
#include <cstdio>
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <poll.h>
using namespace std;

int main()
{
    //创建socket对象
    int Client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (Client == -1)//判断是否创建成功
    {
        cout << "创建失败" << endl;
        close(Client);
        return -1;
    }

    const char* ip = "127.0.0.1";//保存ip地址
    unsigned short port=9527;//保存端口

    //设置服务端
    sockaddr_in addrServer;
    addrServer.sin_addr.s_addr = inet_addr(ip);
    addrServer.sin_port = htons(port);
    addrServer.sin_family = AF_INET;

    //连接
    if (connect(Client, (sockaddr*)&addrServer, sizeof(addrServer))== -1)
    {
        cout << "连接失败" << endl;
        close(Client);
        return -1;
    }
    cout << "连接服务器成功" << endl;

    //接收和发送数据
    char rec[1024];
    char se[1024];

    while(1)
    {
        memset(rec, 0, sizeof(rec));
        memset(se, 0, sizeof(se));
        
        scanf("%s", se);
        if (strcmp(se, "quit") == 0 || strcmp(se, "exit") == 0)
            break;

        if (send(Client, se, sizeof(se), 0) < 0)
            break;
        cout << "发送:" << se << endl;

        if (recv(Client, rec, sizeof(rec), 0) < 0)
            break;
        cout << "接收:" << rec << endl;
    }

    cout << "已与服务端断开连接" << endl;

    close(Client);
    return 0;
}
相关推荐
我不会起名字3225 分钟前
TCP 三次握手为什么是三次:丢包、重传与初始序列号
网络·tcp·原理·握手
Yang961119 分钟前
鼎讯信通DXA-3S光纤熔接机:光缆教学中的技术精粹解析
网络
GeW24 分钟前
新质生产力路线图解读:数据库性能优化与Linux调优专场
linux
必须得开心呀1 小时前
字节序大小端科普
c++·程序人生
xbzb1 小时前
IP、掩码、网关、DNS 到底谁管什么?网络基础与七种设备一次讲清
网络·网关·mac·ip·dns·掩码
会编程的小孩1 小时前
C++ 子集
c++
mounter6251 小时前
深入理解 gccrs:GCC 如何实现 Rust 编译器,以及编译 Linux 内核面临的挑战
linux·驱动开发·rust
垚垚学技术_聚焦云原生1 小时前
Ansible Playbook 进阶:when 条件、loop 循环、handlers 触发器落地
linux·ansible·自动化运维·devops
SunkingYang2 小时前
C++20 vs C++17:新特性对比与用法指南
c++·c++20·特性·版本·新特性·对比·c++17
前进吧-程序员2 小时前
C++20 协程入门实战:从 co_await 到一个 100 行的异步任务调度器
网络·c++·c++20