网络编程Day5

网络编程Day5_第1张图片

1> 使用select实现TCP客户端的并发

#include 
#define SER_PORT 8888
#define SER_IP "192.168.125.64"
#define CLI_PORT 9999
#define CLI_IP "192.168.125.64"
int main(int argc, char const *argv[])
{
    //创建用于连接的套接字
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if (cfd == -1)
    {
        perror("socket error");
        return -1;
    }
    //给套接字绑定端口IP
    struct sockaddr_in cin;
    cin.sin_family = AF_INET;
    cin.sin_port = htons(CLI_PORT);
    cin.sin_addr.s_addr = inet_addr(CLI_IP);
    //绑定,可选
    if (bind(cfd, (struct sockaddr *)&cin, sizeof(cin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    puts("bind success");
    //连接服务器
    //填充服务器地址结构体
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(SER_PORT);
    sin.sin_addr.s_addr = inet_addr(SER_IP);
    if (connect(cfd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        perror("bind sin error");
        return -1;
    }
    puts("connect success");
    //阻塞客户端
    int ret;
    fd_set fd;
    FD_ZERO(&fd);
    FD_SET(0, &fd);
    FD_SET(cfd, &fd);
    ret = select(cfd + 1, &fd, NULL, NULL, NULL);
    char buf[128] = "", buf1[128] = "";
 
    //客户端收发操作
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        memset(buf1, 0, sizeof(buf1));
        //接收服务器消息事件触发
        if (FD_ISSET(cfd, &fd))
        {
            if (recv(cfd, buf1, sizeof(buf1), 0) < 0)
            {
                perror("recv error");
                return -1;
            }
            printf("%s\n", buf1);
            continue;
        }
        //发送事件触发
        if (FD_ISSET(0, &fd))
        {
            fgets(buf, sizeof(buf), stdin);
            buf[strlen(buf) - 1] = '\0';
            if (strcmp(buf, "quit") == 0)
                break;
            if (send(cfd, buf, strlen(buf), 0) < 0)
            {
                perror("send error");
                return -1;
            }
            continue;
        }
    }
END:
    //关闭套接字
    close(cfd);
    return 0;
}

2> 使用poll实现TCP服务器的并发

#include 
#define PORT 8888
#define IP "192.168.125.64"
#define OPEN_MAX 10
int main(int argc, char const *argv[])
{
    //创建tcp监听套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
 
    //2.绑定sockfd
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_port = htons(PORT);
    sin.sin_addr.s_addr = inet_addr(IP);
    if (bind(sockfd, (struct sockaddr *)&sin, sizeof(sin)) == -1)
    {
        perror("bind error");
        return -1;
    }
    puts("bind success");
    //监听listen
    if (listen(sockfd, 128) == -1)
    {
        perror("listen error");
        return -1;
    }
    puts("listen success");
    //poll相应参数准备
    struct pollfd pfd[OPEN_MAX];
    int i = 1, maxi = 1;
    //初始化poll结构中的文件描述符fd
    for (; i < OPEN_MAX; i++)
        pfd[i].fd = -1;
    pfd[0].fd = 0;
    pfd[0].events = POLLIN;
    pfd[1].fd = sockfd;
    pfd[1].events = POLLIN;
 
    //对已连接的客户端的数据处理
    while (1)
    {
        //阻塞检测集合中是否有事件产生,-1表示一直阻塞
        int ret = poll(pfd, maxi + 1, -1);
        struct sockaddr_in cin;
        socklen_t socklen = sizeof(cin);
        //检测0号描述符
        if (pfd[0].revents == POLLIN)
        {
            //终端输入
            char buf[128] = "";
            scanf("%s", buf);
            if (strcmp(buf, "quit") == 0)
            {
                break;
            }
        }
        //监测sockfd是否存在连接
        if (pfd[1].revents == POLLIN)
        {
            int res = 0;
            //获取客户端
            res = accept(sockfd, (struct sockaddr *)&cin, &socklen);
            printf("[%s:%d]发来连接请求\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
            //将提取到的res放入poll结构体数组中,以便于监测
            for (i = 2; i < OPEN_MAX; i++)
            {
                if (pfd[i].fd < 0)
                {
                    pfd[i].fd = res;
                    pfd[i].events = POLLIN;
                    break;
                }
            }
            //maxi更新
            if (i > maxi)
                maxi = i;
            //如果没有就绪的描述符,就继续poll监测,否则继续向下看
            if (--res <= 0)
                continue;
        }
        //继续响应就绪的描述符
        for (i = 2; i <= maxi; i++)
        {
            if (pfd[i].revents == POLLIN)
            {
                int len = 0;
                char buf[128] = "";
                //接受客户端数据
                if ((len = recv(pfd[i].fd, buf, sizeof(buf), 0)) < 0)
                {
                    perror("recv error");
                    return -1;
                }
                else if (len == 0) //客户端关闭连接
                {
                    puts("客户端下线");
                    close(pfd[i].fd);
                    pfd[i].fd = -1;
                }
                else
                {
                    printf("[%s:%d]%s\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), buf);
                    //正常接收到服务器的数据
                    strcat(buf, "^.^");
                    send(pfd[i].fd, buf, sizeof(buf), 0);
                }
 
                //所有的就绪描述符处理完了,就退出当前的for循环,继续poll监测
                if (--ret <= 0)
                    break;
            }
        }
    }
    close(sockfd);
    return 0;
}

你可能感兴趣的:(网络)