TCP高级应用(1)阻塞与非阻塞基本概念

非阻塞应用示例

发送端代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<math.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<time.h>
#include<dirent.h>
#include<sys/errno.h>
#include<sys/wait.h>
#include<signal.h>
#include<sys/param.h>
#include<sys/syslog.h>
#include<limits.h>
#include<sys/time.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/sem.h>
#include<errno.h>
#include<sys/shm.h>
#include<pthread.h>
#include<sys/syscall.h>
#include<semaphore.h>
#include<bits/pthreadtypes.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
#define BUFSIZE 128
int main(int argc,char *argv[])
{
    int server_sockfd,client_sockfd;
    int server_len,client_len;
    struct sockaddr_in server_address;
    struct sockaddr_in client_address;
    int i,byte;
    char char_send[BUFSIZE];
    server_sockfd=socket(AF_INET,SOCK_STREAM,0);    //创建soclet对象
    server_address.sin_family=AF_INET;
    if(inet_aton(argv[1],(struct in_addr *)&server_address.sin_addr.s_addr)==0)    //从argv[1]中提取ip地址且转换为32ip地址
    
        {
            perror(argv[1]);
            exit(EXIT_FAILURE);
        }
    server_address.sin_port=htons(7838);    //使用特定端口7838
    server_len=sizeof(server_address);    
    bind(server_sockfd,(struct sockaddr *)&server_address,server_len);  //绑定IP地址
    listen(server_sockfd,5);    //监听网络
    printf("server wait for connect\n");
    client_len=sizeof(client_address);
    client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_address,(socklen_t *)&client_len);   //等待连接
    for(i=0;i<5;i++)
        {
            memset(char_send,'\0',BUFSIZE);
            printf("input message to send:");
            fgets(char_send,BUFSIZE,stdin);     //首先阻塞在终端接收用户输入
            if(byte=send(client_sockfd,char_send,strlen(char_send),0)==-1)
                {
                    perror("send");
                    exit(EXIT_FAILURE);
                }
            memset(char_send,'\0',BUFSIZE);
            byte=recv(client_sockfd,char_send,BUFSIZE,MSG_DONTWAIT);    //非阻塞接收
            if(byte>0)
                {
                    printf("get %d message:%s",byte,char_send);
                    byte=0;
                }
            else if(byte<0)
                {
                    if(errno==EAGAIN)    //如果是因无数据返回的错误,则继续
                        {
                            errno=0;
                            continue;
                        }
                    else
                        {
                            perror("recv");
                            exit(EXIT_FAILURE);
                        }
                }
        }
    shutdown(client_sockfd,2);    //关闭socket对象
    shutdown(server_sockfd,2);
    
return 0;
}

发送端:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<math.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<time.h>
#include<dirent.h>
#include<sys/errno.h>
#include<sys/wait.h>
#include<signal.h>
#include<sys/param.h>
#include<sys/syslog.h>
#include<limits.h>
#include<sys/time.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/sem.h>
#include<errno.h>
#include<sys/shm.h>
#include<pthread.h>
#include<sys/syscall.h>
#include<semaphore.h>
#include<bits/pthreadtypes.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<sys/socket.h>
#define MAXBUF 128
int main(int argc,char *argv[])
{
    int sockfd,ret,i;
    struct sockaddr_in dest,mine;
    char buffer[MAXBUF+1];
    if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)     //创建socket对象
        {
            perror("Socket");
            exit(EXIT_FAILURE);
        }
    bzero(&dest,sizeof(dest));
    dest.sin_family=AF_INET;
    dest.sin_port=htons(7838);     // 服务器特定端口,与服务器设置一致
    if(inet_aton(argv[1],(struct in_addr *)&dest.sin_addr.s_addr)==0)
        {
            perror("Socket");
            exit(EXIT_FAILURE);
        }
    bzero(&mine,sizeof(mine));
    mine.sin_family=AF_INET;
    mine.sin_port=htons(7839);    //本地端口
    if(inet_aton(argv[2],(struct in_addr *)&mine.sin_addr.s_addr)==0)
        {
            perror(argv[2]);
            exit(EXIT_FAILURE);
        }
    if(bind(sockfd,(struct sockaddr*)&mine,sizeof(struct sockaddr))==-1)   // 绑定自己的ip信息
        {
            perror(argv[3]);
            exit(EXIT_FAILURE);
        }
    if(connect(sockfd,(struct sockaddr *)&dest,sizeof(dest))!=0)
        {
            perror("Connect ");
            exit(EXIT_FAILURE);
        }
    if(fcntl(sockfd,F_SETFL,O_NONBLOCK)==-1)   //设置为非阻塞
        {
            perror("fcntl");
            exit(EXIT_FAILURE);
        }
    while(1)
        {
            bzero(buffer,MAXBUF+1);
            ret=recv(sockfd,buffer,MAXBUF,0);  //因设置为非阻塞,故此操作非阻塞
            if(ret>0)
                {
                    printf("get %d message:%s",ret,buffer);
                    ret=0;
                }
            else if(ret<0)
                {
                    if(errno==EAGAIN)
                        {
                            errno=0;
                            continue;
                        }
                    else
                        {
                            perror("recv");
                            exit(EXIT_FAILURE);
                        }
                }
        memset(buffer,'\0',MAXBUF+1);
        printf("input message to send:");
        fgets(buffer,MAXBUF,stdin);   //在接接收到数据后阻塞在终端,向对方发送数据
        if((ret=send(sockfd,buffer,strlen(buffer),0))==-1)
            {
                perror("send");
                exit(EXIT_FAILURE);
            }
        }
    close(sockfd);    //关闭socket对象

return 0;
}
》》在接收信息时是非阻塞,但是阻塞了终端,在终端无法打印信息,但却在接受信息,具体实现效果如下

发送端:在连续输入hello test go read why  后 接收端:只打印了hello,后面的所有数据都被终端阻塞,等待用户输入一个字符,之后为:

接收到所有数据并打印出来,这说明只是终端被阻塞,并没有阻塞socket对象接收信息。两端口通信成功。都是基于本地IP地址进行同信。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值