POLL函数实现客户端和服务器的互相回传信息。

发布于:2022-12-26 ⋅ 阅读:(386) ⋅ 点赞:(0)

客户端:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include <signal.h>
#include <poll.h>

#define SIZE 64

int main(int argc, char *argv[])
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);//创建网络通信接口
    if(-1 == sockfd)
    {
        perror("socket");
        return -1;
    }

    printf("sockfd=%d\n",sockfd);


    struct sockaddr_in saddr;//服务器的地址结构
    bzero(&saddr,sizeof(saddr));//memset()
    saddr.sin_family = AF_INET;//指定协议族ipv4 
    saddr.sin_port = htons(9999);//端口号:5001~65535 
    saddr.sin_addr.s_addr = inet_addr("127.0.0.1  ");//ip地址 点分式 -> 二进制网络字节序


    int ret = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));//绑定 将服务器的ip和port与sockfd绑定
    if(-1 == ret)
    {
        perror("connect");
        close(sockfd);
        return -1;
    }
    printf("connect success\n");
    //通信
    

    char buf[SIZE] = {0};
    struct pollfd fd[1024]={0};
    fd[0].fd=0;
     fd[0].events=POLLIN;
     fd[1].fd=sockfd;
     fd[1].events=POLLIN;
     int nfds = 2;//最大文件描述符+1
    

    do{
      ret = poll(fd,nfds,-1);//监测是否有文件描述符准备就绪
        if(-1 == ret)
        {
            perror("poll");
            break;
        }
        else if(0 == ret)
        {
            printf("timeout....\n");
            continue;
        }

        if(fd[0].revents&POLLIN)//0准备就绪
        {
            bzero(buf,sizeof(buf));

            fgets(buf,sizeof(buf),stdin);//标准输入获取字符串
            ret = write(sockfd,buf,sizeof(buf));//给服务器写请求
            if(-1 == ret)
            {
                perror("write");
                break;
            }
        }
        if(fd[1].revents&POLLIN)//sockfd可读
        {
            bzero(buf,sizeof(buf));
            ret = read(sockfd, buf, sizeof(buf));//读取服务器回传的内容
            if(-1 == ret)
            {
                perror("read");
                break;
            }
            puts(buf);
        }

    }while(strncmp(buf,"quit",4) != 0);


    close(sockfd);

    return 0;

 

服务器:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/select.h>
#include <poll.h>
#define _GNU_SOURCE         /* See feature_test_macros(7) */
#include <signal.h>
#include <poll.h>


#define SIZE 64

int server_init(char *ipaddr, unsigned short port, int backlog)
{
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);//创建网络通信接口
    if(-1 == sockfd)
    {
        perror("socket");
        return -1;
    }

    //printf("sockfd=%d\n",sockfd);


    struct sockaddr_in saddr;//服务器的地址结构
    bzero(&saddr,sizeof(saddr));//memset()
    saddr.sin_family = AF_INET;//指定协议族ipv4 
    saddr.sin_port = htons(port);//端口号:5001~65535 
    saddr.sin_addr.s_addr = (ipaddr == NULL)? htonl(INADDR_ANY) : inet_addr(ipaddr);//ip地址 点分式 -> 二进制网络字节序


    int ret = bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));//绑定 将服务器的ip和port与sockfd绑定
    if(-1 == ret)
    {
        perror("bind");
        close(sockfd);
        return -1;
    }
    //printf("bind success\n");

    ret = listen(sockfd, backlog);//监听是否有客户端请求连接 sockfd:监听套接字
    if(-1 == ret)
    {
        perror("listen");
        close(sockfd);
        return -1;
    }

    return sockfd;
}

//设置非阻塞
int set_nonblock(int fd)
{
    int flags = fcntl(fd, F_GETFL);//获取fd的状态标志位
    if(-1 == flags)
    {
        perror("fcntl");
        return -1;
    }

    flags |= O_NONBLOCK;//设置非阻塞状态

    return (fcntl(fd, F_SETFL, flags));
}

int main(int argc, char *argv[])
{
    if(argc < 3)
    {
        printf("Usage:%s <ip> <port>\n",argv[0]);
        return -1;
    }
    int sockfd = server_init(argv[1], atoi(argv[2]), 1024);
    if(-1 == sockfd)
    {
        printf("server_init error\n");
        return -1;
    }
    printf("listen....\n");

    struct sockaddr_in caddr;//保存客户端的信息(ip port protocol)
    bzero(&caddr, sizeof(caddr));
    socklen_t clen = sizeof(caddr);

    //rws:用于服务器和连接的客户端通信
    int rws = accept(sockfd, NULL, NULL);//阻塞等待客户端请求连接
    if(-1 == rws)
    {
        perror("accept");
        close(sockfd);
        return -1;
    }

    printf("rws=%d\n",rws);

    //通信
    char buf[SIZE] = {0};

    struct pollfd fd[1024]={0};
    fd[0].fd=0;
    fd[0].events=POLLIN;
    fd[1].fd=rws;
    fd[1].events=POLLIN;
    int nfds = 2;//最大文件描述符+1
    int ret;

    while(1)
    {
       ret = poll(fd,nfds,-1);//监测是否有文件描述符准备就绪
        if(-1 == ret)
        {
            perror("select");
            break;
        }
        else if(0 == ret)
        {
            printf("timeout....\n");
            continue;
        }

        if(fd[0].revents&POLLIN)//读标准输入准备就绪
        {
            bzero(buf,sizeof(buf));
            fgets(buf,sizeof(buf),stdin);
            //回传消息给客户端
            ret = send(rws,buf,sizeof(buf),0);
            if(-1 == ret)
            {
                perror("send");
                break;
            }

        }
        if(fd[1].revents&POLLIN)//rws准备就绪
        {
            bzero(buf, sizeof(buf));
            int ret = recv(rws,buf,sizeof(buf),0);//读客户端消息
            if(-1 == ret)
            {
                perror("recv");
                continue;
            }
            else if(0 == ret)//表示客户端关闭
            {
                printf("client closed\n");
                return -1;
            }

            puts(buf);
        }

    }
    if(-1 == close(rws))
    {


    }
    close(sockfd);

    return 0;

 

运行:

 

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到