NETday5 select

这篇文章展示了两个C语言程序,一个是服务器端,使用了socket、bind、listen和select函数来建立并监听端口,接收客户端连接。另一个是客户端,通过socket和connect与服务器建立连接,使用select进行读写操作。同时,还展示了一个使用poll进行事件监控的例子,实现了客户端发送和接收数据的功能。
摘要由CSDN通过智能技术生成

1.服务器

#include <head.h>
#define ERR_MSG(msg) do{\
    fprintf(stderr,"line: %d\n",__LINE__);\
    perror(msg);\
    return -1;\
}while(0);

#define IP "192.168.0.226"

#define PORT 6555
//另存客户端信息
struct sockaddr_in savecin[1020];
int main(int argc,const char * argv[])
{
    //创建流式字节套
    int sfd = socket(AF_INET,SOCK_STREAM,0);
    if(sfd < 0){
        ERR_MSG("socket");
    }
    printf("sfd = %d\n",sfd);

    //允许端口快速被使用
    int reuse = 1;
    if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)) < 0){
        ERR_MSG("setsockopt");
        return -1;
    }
    printf("允许端口快速被启用成功\n");

    //填充地址信息结构体
    //真实的地址信息结构体根据地址组指定
    struct sockaddr_in sin;

    sin.sin_family = AF_INET;  //族必须是和sdf的族一致
    sin.sin_port = htons(PORT); //端口号
    sin.sin_addr.s_addr = inet_addr(IP); //IP地址


    //将IP和端口绑定到socket上
    if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin)) < 0){
        ERR_MSG("bind");
    }
    printf("bind success _______%d__________\n",__LINE__);//绑定成功

    //将套接字设置为被动监听状态
    if(listen(sfd,128) < 0){
        ERR_MSG("listen");
    }
    struct sockaddr_in cin;
    socklen_t len = sizeof(cin);

    //创建readfd
    char buf[128] ="";
    char str[128]= "";
    int newfd;
    int maxfd = sfd;
    int res = 0;
    fd_set readfd;
    FD_ZERO(&readfd);

    fd_set tempfd = readfd;

    FD_SET(0,&readfd);
    FD_SET(sfd,&readfd);

    int i = 0;
    int s_res = 0;
    while(1){
        tempfd = readfd;
        s_res =select(maxfd+1,&tempfd,NULL,NULL,NULL);
        if(s_res < 0){
            ERR_MSG("select");
            return -1;
        }
        for(i =  0; i <= maxfd; i++){   
            if(!(FD_ISSET(i,&tempfd))){
                continue;
            }
            if(0 == i){
                memset(buf,0,sizeof(buf));
                printf("触发键盘输入事件>>> ");
                bzero(buf, sizeof(buf));
                int a = -1;
                scanf("%d %s",&a,buf);
                //buf[strlen(buf)-1] = '\0';
                send(a,buf,sizeof(buf),0);
            }else if(sfd == i){
                printf("触发连接\n");
                newfd = accept(sfd,(struct sockaddr*)&cin,&len);
                if(newfd < 0){
                    ERR_MSG("accept");
                    return -1;
                }
                
                savecin[newfd-4] = cin;
                printf("[%s:%d] newfd = %d连接成功__%d__\n",inet_ntoa(savecin[i-4].sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
                FD_SET(newfd,&readfd);
                if(newfd > maxfd){
                    maxfd = newfd;
                }
                //存在数组中

            }else{
                memset(str,0,sizeof(str));
               res = recv(i,str,sizeof(str),0);
               if(res < 0){
                    ERR_MSG("recv");
                    return -1;
               }else if(0 == res){
                    printf("[%s][%d]断开连接\n",inet_ntoa(savecin[i-4].sin_addr),ntohs(savecin[i-4].sin_port));

                    close(i);
                    FD_CLR(i,&readfd);
                    int j = 0;
                    for(j = maxfd; j >= 0; j--){
                        if(FD_ISSET(j,&readfd)){
                            maxfd = j;
                            break;
                        }
                        if(j < 0){
                            maxfd = -1;
                        }
                        continue;
                    }
                    
               }
               
               printf("[%s][%d] newfd:%d %s\n",inet_ntoa(savecin[i-4].sin_addr),ntohs(savecin[i-4].sin_port),newfd,str);
     
            }
        }

    }
    

    return 0;
}

服务器

#include <head.h>
#define ERR_MSG(msg) do{\
    fprintf(stderr,"line: %d\n",__LINE__);\
    perror(msg);\
    return -1;\
}while(0);

#define IP "192.168.0.226"

#define PORT 6555
int main(int argc,const char * argv[])
{
    //cj
    int sfd = socket(AF_INET,SOCK_STREAM,0);
    if(sfd < 0){
        ERR_MSG("socket");
    } 
    //不一定需要绑定

        //填充地址信息结构体
    //真实的地址信息结构体根据地址组指定
    struct sockaddr_in sin;

    sin.sin_family = AF_INET;  //族必须是和sdf的族一致
    sin.sin_port = htons(PORT); //端口号
    sin.sin_addr.s_addr = inet_addr(IP); //IP地址
    socklen_t len = sizeof(sin);

    //创建流式字节套(客户端)
    int ret = connect(sfd, (struct sockaddr *)&sin, sizeof(sin));
    if(ret < 0){perror("connect"); return -1;}
    else{printf("连接套接字成功\n");}

    //connect(cfd,(struct sockaddr*)&sin,sizeof(sin));
    
    char buf[128] ="";
    char str[128] ="";
    int res = 0;
    fd_set readfd;
    FD_SET(0,&readfd);
    FD_SET(sfd,&readfd);
    while(1){
        res = select(sfd+1,&readfd,NULL,NULL,NULL);
        if(0 == res){
            ERR_MSG("select");
        }
        if(FD_ISSET(0,&readfd)){
            bzero(buf, sizeof(buf));
            fgets(buf, sizeof(buf), stdin);
            buf[strlen(buf)-1] = '\0';
            send(sfd,buf,sizeof(buf),0);
        }
        if(FD_ISSET(sfd,&readfd)){
            memset(str,0,sizeof(str));
            res = recv(sfd,str,sizeof(str),0);
            if(res < 0){
                ERR_MSG("recv");
                return -1;
            }
            printf("%s\n",str);
        }
        FD_SET(0,&readfd);
        FD_SET(sfd,&readfd);

    }

    return 0;
}

2. poll

#include <head.h>

 
#define IP "192.168.8.220"
#define PORT 6688
 
int ret = 0;
ssize_t res = 0;
 
int main(int argc, char const *argv[])
{
    int cfd = socket(AF_INET, SOCK_STREAM, 0);
    if(cfd < 0){perror("socket"); return -1;}
    else{printf("创建套接字成功...\n");}
 
    struct sockaddr_in sin;
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr(IP);
    sin.sin_port = ntohs(PORT);
 
    ret = connect(cfd, (struct sockaddr *)&sin, sizeof(sin));
    if(ret < 0){perror("connect"); return -1;}
    else{printf("连接套接字成功...\n");}
 
    struct pollfd fds[2];
    fds[0].fd = 0;
    fds[0].events = POLLIN;
    fds[1].fd = cfd;
    fds[1].events = POLLIN;
 
    char buf[128] = "";
 
    while(1)
    {
        ret = poll(fds, 2, -1);
        if(ret < 0){perror("poll"); continue;}
        else if(0 == ret){printf("超时...\n"); continue;}
        else
        {
            if(fds[0].revents & POLLIN)
            {
                bzero(buf, sizeof(buf));
                fgets(buf, sizeof(buf), stdin);
                buf[strlen(buf)-1] = '\0';
                res = send(cfd, buf, sizeof(buf), 0);
                if(res < 0){perror("send"); continue;}
                else{printf("已发送: %s\n", buf);}
 
                if(0 == strcasecmp(buf, "quit"))
                {
                    break;
                }
            }
            if(fds[1].revents & POLLIN)
            {
                bzero(buf, sizeof(buf));
                res = recv(cfd, buf, sizeof(buf), 0);
                if(res < 0){perror("recv"); continue;}
                else{printf("收到: %s\n", buf);}
                if(0 == strcasecmp(buf, "quit"))
                {
                    printf("服务器离开...\n");
                    break;
                }
            }
        }
    }
 
    close(cfd);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值