当前位置: 首页 > news >正文

Linux socket编程实战(非阻塞)

socket在创建的时候默认是阻塞的,要想设置为非阻塞的有以下几种方法:

1.ioctl 和 fcntl 设置已经创建socket的fd

ioctl用于设备控制

  #include <sys/ioctl.h>

  int ioctl(int fd, unsigned long request, ...);

fcntl用于文件控制 

 #include <unistd.h>
 #include <fcntl.h>

 int fcntl(int fd, int cmd, ... /* arg */ );

通过下面方式设置:

flags = fcntl(sfd, F_GETFL);
flags |= O_NONBLOCK;
fcntl(sfd, F_SETFL, flags);

2.在创建socket的时候设置

int fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);

3.accept4

int accept4(int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags);

   flags 设置成 SOCK_NONBLOCK,这种方式是在服务端。

 

服务端设置5秒后再接收数据:

#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdio.h>
#include<errno.h>


int main(int argc, char* argv[]){

int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd < 0){
	printf("create socket failed!, errno=%d\n",errno);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(8080);

int ret;
ret = bind(fd, (struct sockaddr*) &addr, sizeof(addr));
if(ret == -1){
	printf("bind failed!, errno=%d",errno);
	close(fd);
}
ret = listen(fd, SOMAXCONN);
if(ret == -1){
	printf("listen failed!, errno=%d",errno);
}
struct sockaddr_in clientaddr;
socklen_t clientaddrlen = sizeof(clientaddr);
int afd = accept(fd, (struct sockaddr*) &clientaddr, &clientaddrlen);
if(afd != -1){
	printf("A client connected!,ip=%s,port=%d\n",inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
	char buf[256] = {0};
    sleep(5);
	ret = recv(afd, buf, 256, 0);
	if(ret > 0){
		printf("recv %d byte:%s\n",ret,buf);
	}
	else if(ret == -1){
		printf("recv error!,errno=%d\n",errno);
	}
	else{
		printf("client disconnect!\n");
	}	
}
else{
	printf("accept failed!,errno=%d\n",errno);
}
}

 客户端设置非阻塞,验证一下send非阻塞的现象:

#include<sys/socket.h>
#include<sys/types.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<stdio.h>
#include <stdlib.h>
#include<errno.h>
#include<string.h>
#include <fcntl.h>

int main(int argc, char* argv[]){
	

if(argc != 3){
	printf("please input IP port\n");
}
char* ip = argv[1];
unsigned int port = atoi(argv[2]);
int fd = socket(AF_INET, SOCK_STREAM, 0);
if(fd < 0){
	printf("create socket failed!, errno=%d\n",errno);
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);

int ret;
ret = connect(fd, (struct sockaddr*) &addr, sizeof(addr));
if(ret == -1){
	printf("connect failed!, errno=%d",errno);
}
else{
	//连接成功后将fd设置为非阻塞
	int flags = fcntl(fd, F_GETFL);
    flags |= O_NONBLOCK;
    ret = fcntl(fd, F_SETFL, flags);
	if(ret == -1){
		printf("set O_NONBLOCK failed!,errno=%d\n",errno);
	}
	char *buf = "hello, I am a client!";
	int cnt = 0;
	while(1){
			ret = send(fd, buf, strlen(buf), 0);
			if(ret > 0){
				cnt++;
				printf("send %d byte:%s,cnt = %d\n",ret,buf,cnt);
			}
			else if(ret == -1){
				if(errno == EAGAIN){
					printf("send try again\n");
					sleep(1);
					continue;
				}
				else
				printf("send error!,errno=%d\n",errno);
			}
			else{
				printf("server disconnect!\n");
			}
	}
	
}
	
}

 

相关文章:

  • coredump配置调试
  • Linux I/O复用技术---select
  • log4cpp的使用
  • Linux I/O复用技术---poll
  • Linux I/O复用技术---epoll
  • 网络通信基础知识(tcp/ip)
  • protobuf(C++)的使用(windows)
  • 常用字符串函数的实现
  • 使用宏定义max函数
  • libevent的使用
  • 线程的同步手段
  • 单台百万并发
  • 数据结构与算法知识点
  • fastdfs+nginx集群搭建
  • zeromq的使用(windows)
  • C++入门教程(10):for 语句
  • codis proxy处理流程
  • DOM的那些事
  • EventListener原理
  • leetcode46 Permutation 排列组合
  • Python - 闭包Closure
  • vue 个人积累(使用工具,组件)
  • Vue组件定义
  • Yeoman_Bower_Grunt
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 理解在java “”i=i++;”所发生的事情
  • 前端设计模式
  • 融云开发漫谈:你是否了解Go语言并发编程的第一要义?
  • 如何设计一个微型分布式架构?
  • ​VRRP 虚拟路由冗余协议(华为)
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • #stm32整理(一)flash读写
  • #微信小程序(布局、渲染层基础知识)
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (3)STL算法之搜索
  • 、写入Shellcode到注册表上线
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .net core 连接数据库,通过数据库生成Modell
  • .NET程序员迈向卓越的必由之路
  • [1]-基于图搜索的路径规划基础
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [30期] 我的学习方法
  • [Asp.net mvc]国际化
  • [C++] cout、wcout无法正常输出中文字符问题的深入调查(1):各种编译器测试
  • [JavaScript]_[初级]_[关于forof或者for...of循环语句的用法]
  • [LeetCode] Verify Preorder Sequence in Binary Search Tree 验证二叉搜索树的先序序列
  • [LeetCode]Multiply Strings
  • [linux] 创建用户
  • [Linux]——彻底学通权限
  • [Linux]创建新用户并授予root权限
  • [math]判断线段是否相交及夹角
  • [NISACTF 2022]sign-ezc++
  • [py]python自省工具
  • [SCM]源码管理 - perforce高级操作