1.使用poll实现client的收发功能 2.输入键盘事件,响应键盘事件,输入鼠标事件,响应鼠标事件(两路IO)poll

使用poll实现client的收发功能

未注释版本

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <poll.h>

int main(int argc, char const *argv[])
{
    char buf[128] = {0};
    int sockfd = sock(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(atoi(argv[2]));
    saddr.sin_addr.s_addr = inet_addr(argv[1]);
    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect err");
        return -1;
    }
    struct pollfd fds[100];
    fds[0].fd = 0;
    fds[0].events = POLLIN;
    fds[1].fd = sockfd;
    fds[1].events = POLLIN;
    int last = 1;
    while (1)
    {
        int ret = poll(fds, last + 1, -1);
        if (ret < 0)
        {
            perror("poll err");
            return -1;
        }
        if (fds[0].revents == POLLIN)
        {
            fgets(buf, sizeof(buf), stdin);
            if (buf[strlen(buf) - 1] == '\n')
            {
                buf[strlen(buf) - 1] = '\0';
            }
            send(sockfd, buf, sizeof(buf), 0);
        }
        if (fds[1].revents == POLLIN)
        {
            int recv = recv(sockfd, buf, sizeof(buf), 0);
            if (recv < 0)
            {
                perror("recv err");
                return -1;
            }
            else
            {
                printf("%s\n", buf);
            }
        }
    }
    close(sockfd);
    return 0;
}

加注释版本

#include <stdio.h>      // 包含标准输入输出库
#include <stdlib.h>     // 包含标准库函数
#include <string.h>     // 包含字符串处理函数
#include <sys/socket.h> // 包含socket API的函数
#include <netinet/in.h> // 包含Internet地址族的定义
#include <arpa/inet.h>  // 包含INET地址转换函数
#include <unistd.h>     // 包含UNIX标准函数
#include <sys/types.h>  // 包含系统数据类型定义
#include <netinet/ip.h> // 包含IP协议的定义
#include <poll.h>       // 包含poll函数及相关定义

int main(int argc, const char *argv[])
{
    // 创建一个socket,AF_INET表示IPv4,SOCK_STREAM表示TCP
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket is err:"); // 打印socket创建错误信息
        return -1;
    }

    // 配置服务器地址结构
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET; // 地址族为IPv4
    saddr.sin_port = htons(atoi(argv[2])); // 设置端口号,htons用于将主机字节顺序转换为网络字节顺序
    saddr.sin_addr.s_addr = inet_addr(argv[1]); // 设置服务器IP地址

    // 连接到服务器
    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect is err:"); // 打印连接错误信息
        return -1;
    }

    // 1. 创建结构体数组,用于poll函数
    struct pollfd fds[100];

    // 2. 将需要关注的文件描述符和事件类型添加到结构体数组中
    fds[0].fd = 0; // 0表示标准输入(stdin)
    fds[0].events = POLLIN; // 关注输入事件

    fds[1].fd = sockfd; // sockfd为与服务器建立连接的socket
    fds[1].events = POLLIN; // 关注输入事件

    // 3. 保存有效文件描述符的数量
    int nfds = 1;

    while (1)
    {
        // 4. 调用poll函数,等待事件发生
        int ret = poll(fds, nfds + 1, -1); // -1表示无限等待
        if (ret < 0)
        {
            perror("poll is err:"); // 打印poll错误信息
            return -1;
        }
        char buf[128] = {0}; // 缓冲区,用于存放数据

        // 5. 处理发生事件的文件描述符
        if (fds[0].revents & POLLIN) // 检查标准输入是否有数据
        {
            fgets(buf, sizeof(buf), stdin); // 从标准输入读取数据
            if (buf[strlen(buf) - 1] == '\n') // 如果最后一个字符是换行符
                buf[strlen(buf) - 1] = '\0'; // 将换行符替换为字符串结束符
            // 发送数据到服务器
            send(sockfd, buf, sizeof(buf), 0);
        }
        if (fds[1].revents & POLLIN) // 检查socket是否有数据
        {
            // 接收来自服务器的数据
            int recvbyte = recv(sockfd, buf, sizeof(buf), 0);
            if (recvbyte < 0)
            {
                perror("recv is err:"); // 打印接收数据错误信息
                return -1;
            }
            else
            {
                printf("%s\n", buf); // 打印接收到的数据
            }
        }
    }

    close(sockfd); // 关闭socket
    return 0;
}

输入键盘事件,响应键盘事件,输入鼠标事件,响应鼠标事件(两路IO)poll

未注释版本

#include <stdio.h>
#include <poll.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char const *argv[])
{
    int ret;
    char buf[128] = {0};
    int fd = open("/dev/input/mouse0", O_RDONLY);
    if (fd < 0)
    {
        perror("open err");
        return -1;
    }
    // 1.创建结构体数组
    struct pollfd fds[2];
    // 2.将关心的文件描述符添加到数组中,并赋予事件
    fds[0].fd = 0;          // 键盘
    fds[0].events = POLLIN; // 想要发生的事件
    // fds[0].revents=;//实际发生的事件

    fds[1].fd = fd;
    fds[1].events = POLLIN;
    // 3.保存数组内最后一个有效元素的下标
    int last = 1;
    // 4.调用poll函数,监听
    while (1)
    {

        ret = poll(fds, last + 1, 2000);
        if (ret < 0)
        {
            perror("poll err");
            return -1;
        }
        else if (ret == 0)
        {
            printf("time out\n");
        }
        // 5.判断结构体内文件描述符实际触发的事件
        if (fds[0].revents == POLLIN)
        {
            // 6.根据不同文件描述符触发的不同事件做对应的逻辑处理
            fgets(buf, sizeof(buf), stdin);
            printf("keybroad:%s\n", buf);
        }
        if (fds[1].revents == POLLIN)
        {
            read(fd, buf, sizeof(buf));
            printf("mouse:%s\n", buf);
        }
        memset(buf, 0, sizeof(buf));
    }

    close(fd);

    return 0;
}

有注释版本

#include <stdio.h>      // 包含标准输入输出库
#include <poll.h>       // 包含poll函数及相关定义
#include <sys/time.h>   // 包含时间函数
#include <sys/types.h>  // 包含系统数据类型定义
#include <unistd.h>     // 包含UNIX标准函数
#include <sys/stat.h>   // 包含文件状态定义
#include <fcntl.h>      // 包含文件控制定义
#include <string.h>     // 包含字符串处理函数

int main(int argc, char const *argv[])
{
    int ret;            // 用于存储函数返回值
    char buf[128] = {0}; // 缓冲区,用于存储读取的数据
    int fd = open("/dev/input/mouse0", O_RDONLY); // 打开鼠标设备文件,只读模式
    if (fd < 0)         // 检查文件描述符是否有效
    {
        perror("open err"); // 打印打开文件错误信息
        return -1;        // 返回错误码
    }
    // 1. 创建结构体数组,用于poll函数
    struct pollfd fds[2];
    // 2. 将关心的文件描述符添加到数组中,并赋予事件
    fds[0].fd = 0;          // 设置文件描述符0(标准输入)
    fds[0].events = POLLIN; // 关注输入事件(数据可读)
    // fds[0].revents=;// 实际发生的事件

    fds[1].fd = fd;        // 设置文件描述符fd(鼠标设备)
    fds[1].events = POLLIN; // 关注输入事件(数据可读)
    // 3. 保存数组内最后一个有效元素的下标
    int last = 1; // 表示最后一个有效的文件描述符索引
    // 4. 调用poll函数,监听事件
    while (1)
    {
        ret = poll(fds, last + 1, 2000); // 监听文件描述符数组中的事件,超时时间2000毫秒
        if (ret < 0)  // 检查poll函数返回值是否小于0,表示出错
        {
            perror("poll err"); // 打印poll错误信息
            return -1; // 返回错误码
        }
        else if (ret == 0) // 检查poll函数返回值是否为0,表示超时
        {
            printf("time out\n"); // 打印超时信息
        }
        // 5. 判断结构体内文件描述符实际触发的事件
        if (fds[0].revents & POLLIN) // 检查标准输入是否有数据可读
        {
            // 6. 根据不同文件描述符触发的不同事件做对应的逻辑处理
            fgets(buf, sizeof(buf), stdin); // 从标准输入读取数据
            printf("keybroad:%s\n", buf); // 打印读取到的键盘输入数据
        }
        if (fds[1].revents & POLLIN) // 检查鼠标设备是否有数据可读
        {
            read(fd, buf, sizeof(buf)); // 从鼠标设备读取数据
            printf("mouse:%s\n", buf); // 打印读取到的鼠标输入数据
        }
        memset(buf, 0, sizeof(buf)); // 清空缓冲区
    }

    close(fd); // 关闭文件描述符

    return 0; // 返回成功
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值