socket之recv() 阻塞&非阻塞

server.c
 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
 
#define MYPORT 8100 //连接时使用的端口
#define MAXCLINE 5 //连接队列中的个数
int conn_amount; //当前的连接数
 
 
int main(void)
{
	int sock_fd,new_fd; //监听套接字 连接套接字
	struct sockaddr_in server_addr; // 服务器的地址信息
	struct sockaddr_in client_addr; //客户端的地址信息
	socklen_t sin_size;
	int yes = 1;
	char buf[1024];
	int ret;
	int i;
 
	//建立sock_fd套接字
	if((sock_fd = socket(AF_INET,SOCK_STREAM,0))==-1)
	{
		perror("setsockopt");
		exit(1);
	}
	printf("sockect_fd = %d\n", sock_fd);
 
	server_addr.sin_family = AF_INET; //主机字节序
	server_addr.sin_port = htons(MYPORT);
	server_addr.sin_addr.s_addr = INADDR_ANY;//通配IP
	memset(server_addr.sin_zero,'\0',sizeof(server_addr.sin_zero));
 
	if(bind(sock_fd,(struct sockaddr *)&server_addr,sizeof(server_addr)) == -1)
	{
		perror("bind error!\n");
		exit(1);
	}
	if(listen(sock_fd,MAXCLINE)==-1)
	{
		perror("listen error!\n");
		exit(1);
	}
	printf("listen port %d\n",MYPORT);
    new_fd = accept(sock_fd,(struct sockaddr *)NULL, NULL);
    if(new_fd == -1){
        printf("accept socket error: %s\n",strerror(errno));
    }
    int count = 0;
int flag = 0;
//MSG_DONTROUTE 绕过路由表查找。
//MSG_DONTWAIT 仅本操作非阻塞。
//MSG_OOB 发送或接收带外数据。
//MSG_PEEK 窥看外来消息。
//MSG_WAITALL 等待所有数据。
	while(1)
    {
        printf("第 %d 次recv \n",++count);
        ret = recv(new_fd,buf,sizeof(buf),flag);
        if(ret > 0){
            printf("收到 %d Byte[%s] \n",ret,buf);
        }else if (ret < 0){
            if(ret == EAGAIN){
                printf("没有数据可读\n");
            }
        }else{
            printf("连接断开\n");
            break;
        }
        sleep(1);
 
    }
}
 
client.c
//客户端
#include <sys/types.h> 
#include <sys/socket.h> 
#include <stdio.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#define SERVER_IP "192.192.255.63"
int main() 
{ 
	int client_sockfd; 
	int len; 
	struct sockaddr_in address;//服务器端网络地址结构体 
	int result; 
    int count = 0;
    char msg[16];
	client_sockfd = socket(AF_INET, SOCK_STREAM, 0);//建立客户端socket 
	address.sin_family = AF_INET; 
	//address.sin_addr.s_addr = inet_addr(SERVER_IP);
	address.sin_addr.s_addr =INADDR_ANY; 
	address.sin_port = htons(8100); 
	len = sizeof(address); 
	result = connect(client_sockfd, (struct sockaddr *)&address, len); 
	if(result == -1) 
	{ 
		perror("oops: client2"); 
		exit(1); 
	} 
    int flag = 0;
    while(1){
        memset(msg,0,sizeof(msg));
        sprintf(msg,"client-> send%d",count++);
        send(client_sockfd, msg, sizeof(msg),flag); 
        printf("client have send %s \n",msg);
        sleep(15);
    }
	close(client_sockfd); 
 
	return 0; 
}
 
  1. recv 默认是阻塞还是非阻塞?
    这里把client发送一次消息后(为了证明server能收到),sleep150s,如果recv一直轮训接收那就是非阻塞,如果一直等,那就是默认阻塞,这里recv flag = 0;

在这里插入图片描述
第一次收到后,一直阻塞,所以默认是阻塞的,即收不到消息一直等待;

  1. 其他flag参数
    2.1 MSG_DONTWAIT
    修改server.c - > int flag = MSG_DONTWAIT;
    在这里插入图片描述
    这里的执行结果可以看到此时recv不是一直等待,而是返回进行了后续的recv操作;

2.2 MSG_WAITALL
修改server.c - > int flag = MSG_WAITALL; char buf[24];

server.c 一次需要接收24 Byte,而client一次发送才14Byte,看recv如何表现

在这里插入图片描述
每次接收24 Byte(buf的size)才返回,即MSG_WAITALL使用的时候,把recv的buf填满才返回;

posted @ 2022-07-19 09:05  萧海~  阅读(841)  评论(0编辑  收藏  举报