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;

socket之recv() 阻塞&非阻塞_套接字


第一次收到后,一直阻塞,所以默认是阻塞的,即收不到消息一直等待;

  1. 其他flag参数
    2.1 MSG_DONTWAIT
    修改server.c - > int flag = MSG_DONTWAIT;
  2. socket之recv() 阻塞&非阻塞_#include_02

  3. 这里的执行结果可以看到此时recv不是一直等待,而是返回进行了后续的recv操作;

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

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

socket之recv() 阻塞&非阻塞_#define_03


每次接收24 Byte(buf的size)才返回,即MSG_WAITALL使用的时候,把recv的buf填满才返回;