Unix网络编程学习日记(四):基于select的单线程半双工socket客户端的实现

7 篇文章 0 订阅
6 篇文章 0 订阅

select()和pselect()允许程序监控多个文件描述符,等待一个或多个文件描述符变为I/O操作的“就绪”状态。一个“就绪”状态的文件描述符被认为可以接受内核提供的IO操作,比如不被阻塞地“read()”。
有趣的是,Unix的标准输入/输出也是一类文件描述符,可以和socket描述符同时被监听。所以,可以用select监听socket和stdin,保证实时接收网络数据的同时又不阻塞住键盘输入。
这相当于学习笔记(一)中单线程半双工实现的实时性扩展,(一)中的程序需要手动从接收缓冲区刷新接收到的数据。
这里写图片描述

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define  BUFSIZE 1024
int main()
{
    char buf[BUFSIZE];
    int sockfd;
    if((sockfd = socket(AF_INET,SOCK_STREAM,0)) <0)
    {
        perror("Create socket failed");
        exit(-1);
    }
    struct sockaddr_in addr;
    memset(&addr,0,sizeof(struct sockaddr_in));
    char serverIP[15];
    int serverPort;
    printf("Server IP:");
    scanf("%s",serverIP);
    printf("Server port:");
    scanf("%d",&serverPort);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(serverPort);
    addr.sin_addr.s_addr = inet_addr(serverIP);
    if(connect(sockfd,(struct sockaddr *)(&addr),sizeof(struct sockaddr)) < 0)
    {
        perror("Connection error!");
        exit(-1);
    }
    else
    {
        printf("Connected:%s:%d\n",serverIP,serverPort);
    }
    //fcntl(sockfd,F_SETFL,O_NONBLOCK);//设置socket非阻塞模式
    fd_set rset;
    int n;
    FD_ZERO(&rset);
    for(;;)
    {
        FD_SET(STDIN_FILENO,&rset);
        FD_SET(sockfd,&rset);
        select(sockfd +1,&rset,NULL,NULL,NULL);

        if(FD_ISSET(sockfd,&rset))
        {
            memset(buf,0,sizeof(buf));
            n = recv(sockfd,buf,BUFSIZE,0);
            if(n == 0)
            {
                printf("Sever terminated prematurely\n");
                exit(0);
            }
            else
            {
                printf("[recv]%s\n",buf);
            }
        }
        if(FD_ISSET(STDIN_FILENO,&rset))
        {
            n = read(STDIN_FILENO,buf,BUFSIZE);
            if( n <=1)
                continue;
            else
                send(sockfd,buf,n,0);
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值